png.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:9k
源码类别:

Windows CE

开发平台:

C/C++

  1. /*****************************************************************************
  2.  *
  3.  * This program is free software ; you can redistribute it and/or modify
  4.  * it under the terms of the GNU General Public License as published by
  5.  * the Free Software Foundation; either version 2 of the License, or
  6.  * (at your option) any later version.
  7.  *
  8.  * This program is distributed in the hope that it will be useful,
  9.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11.  * GNU General Public License for more details.
  12.  *
  13.  * You should have received a copy of the GNU General Public License
  14.  * along with this program; if not, write to the Free Software
  15.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  16.  *
  17.  * $Id: png.c 313 2005-10-29 15:15:47Z picard $
  18.  *
  19.  * The Core Pocket Media Player
  20.  * Copyright (c) 2004-2005 Gabor Kovacs
  21.  *
  22.  ****************************************************************************/
  23.  
  24. #include "../common/common.h"
  25. #include "../common/zlib/zlib.h"
  26. #include "png.h"
  27. typedef struct png
  28. {
  29. codec Codec;
  30. buffer Buffer;
  31. bool_t ErrorShowed;
  32. const uint8_t* Ptr;
  33. } png;
  34. static int UpdateInput(png* p)
  35. {
  36. p->ErrorShowed = 0;
  37. BufferClear(&p->Buffer);
  38. if (p->Codec.In.Format.Type == PACKET_VIDEO)
  39. {
  40. PacketFormatCopy(&p->Codec.Out.Format,&p->Codec.In.Format);
  41. p->Codec.Out.Format.Format.Video.Pixel.Flags = PF_RGB;
  42. p->Codec.Out.Format.Format.Video.Pixel.BitCount = 24;
  43. p->Codec.Out.Format.Format.Video.Pixel.BitMask[0] = 0xFF;
  44. p->Codec.Out.Format.Format.Video.Pixel.BitMask[1] = 0xFF00;
  45. p->Codec.Out.Format.Format.Video.Pixel.BitMask[2] = 0xFF0000;
  46. DefaultPitch(&p->Codec.Out.Format.Format.Video);
  47. }
  48. return ERR_NONE;
  49. }
  50. static NOINLINE int NotSupported(png* p)
  51. {
  52. if (!p->ErrorShowed)
  53. {
  54. p->ErrorShowed = 1;
  55. ShowError(p->Codec.Node.Class,PNG_ID,PNG_NOT_SUPPORTED);
  56. }
  57. return ERR_NOT_SUPPORTED;
  58. }
  59. static NOINLINE int Read32(png* p)
  60. {
  61. int v = LOAD32BE(p->Ptr);
  62. p->Ptr += 4;
  63. return v;
  64. }
  65. static int Predictor(int Left,int Up,int Corner)
  66. {
  67. int i = Left+Up-Corner;
  68. int a = abs(i-Left);
  69. int b = abs(i-Up);
  70. int c = abs(i-Corner);
  71. return (a<=b && a<=c)?Left:((b<=c)?Up:Corner);
  72. }
  73. static void Filter(int Mode,const uint8_t* Src,const uint8_t* DstLast,uint8_t* Dst,int Ch,int BytesPerRow)
  74. {
  75. const uint8_t* DstPrev;
  76. const uint8_t* DstLastPrev;
  77. int i;
  78. DstLastPrev = DstLast;
  79. DstPrev = Dst;
  80. if (!DstLast)
  81. {
  82. if (Mode==2) Mode=0;
  83. if (Mode==4) Mode=1;
  84. }
  85. switch (Mode)
  86. {
  87. case 1: // subtraction filter
  88. for (i=0;i<Ch;++i)
  89. *(Dst++) = *(Src++);
  90. for (BytesPerRow-=Ch;BytesPerRow>0;--BytesPerRow)
  91. *(Dst++) = (uint8_t)(*(Src++) + *(DstPrev++));
  92. break;
  93. case 2: // up filter
  94. for (;BytesPerRow>0;--BytesPerRow)
  95. *(Dst++) = (uint8_t)(*(Src++) + *(DstLast++));
  96. break;
  97. case 3: // average filter
  98. if (DstLast)
  99. {
  100. for (i=0;i<Ch;++i)
  101. *(Dst++) = (uint8_t)(*(Src++) + (*(DstLast++)>>1));
  102. for (BytesPerRow-=Ch;BytesPerRow>0;--BytesPerRow)
  103. *(Dst++) = (uint8_t)(*(Src++) + ((*(DstPrev++)+*(DstLast++))>>1));
  104. }
  105. else
  106. {
  107. for (i=0;i<Ch;++i)
  108. *(Dst++) = *(Src++);
  109. for (BytesPerRow-=Ch;BytesPerRow>0;--BytesPerRow)
  110. *(Dst++) = (uint8_t)(*(Src++) + (*(DstPrev++)>>1));
  111. }
  112. break
  113. ;
  114. case 4: // paeth prediction
  115. for (i=0;i<Ch;++i)
  116. *(Dst++) = (uint8_t)(*(Src++) + Predictor(0,*(DstLast++),0));
  117. for (BytesPerRow-=Ch;BytesPerRow>0;--BytesPerRow)
  118. *(Dst++) = (uint8_t)(*(Src++) + Predictor(*(DstPrev++),*(DstLast++),*(DstLastPrev++)));
  119. break;
  120. default: // copy
  121. memmove(Dst,Src,BytesPerRow);
  122. break;
  123. }
  124. }
  125. static int Process(png* p, const packet* Packet, const flowstate* State)
  126. {
  127. static const uint8_t Magic[8] = {0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A};
  128. rgb Pal[256];
  129. const uint8_t* PtrEnd;
  130. uint8_t* LastRow = NULL;
  131. int Ch = 0;
  132. video Video;
  133. int BytesPerRow=0,Left=0,Row=0;
  134. z_stream Inflate;
  135. if (!Packet)
  136. return ERR_NEED_MORE_DATA;
  137. p->Ptr = Packet->Data[0];
  138. PtrEnd = p->Ptr + Packet->Length;
  139. if (Packet->Length<16 || memcmp(p->Ptr,Magic,8)!=0)
  140. return ERR_INVALID_DATA;
  141. p->Ptr += 8;
  142. memset(&Video,0,sizeof(Video));
  143. BufferDrop(&p->Buffer);
  144. while (p->Ptr+8<=PtrEnd)
  145. {
  146. int i;
  147. int Len = Read32(p);
  148. int Id = Read32(p);
  149. const uint8_t* Next = p->Ptr+Len+4; //dword CRC
  150. if (Next > PtrEnd)
  151. break;
  152. switch (Id)
  153. {
  154. case FOURCCBE('I','H','D','R'):
  155. if (Len<13)
  156. return ERR_INVALID_DATA;
  157. Video.Width = Read32(p);
  158. Video.Height = Read32(p);
  159. Video.Pixel.BitCount = p->Ptr[0];
  160. Video.Aspect = ASPECT_ONE; //todo
  161. if (p->Ptr[2] != 0 || // compression
  162. p->Ptr[3] != 0 || // filter mode
  163. p->Ptr[4] != 0)   // interlaced
  164. return NotSupported(p);
  165. if (Video.Pixel.BitCount != 8)
  166. return NotSupported(p);
  167. if (p->Ptr[1] & 1)
  168. {
  169. if (p->Ptr[1] & 4)
  170. return NotSupported(p); //todo
  171. Video.Pixel.Flags |= PF_PALETTE;
  172. Ch = 1;
  173. }
  174. else
  175. if (p->Ptr[1] & 2)
  176. {
  177. Video.Pixel.Flags |= PF_RGB;
  178. Video.Pixel.BitMask[0] = 0xFF;
  179. Video.Pixel.BitMask[1] = 0xFF00;
  180. Video.Pixel.BitMask[2] = 0xFF0000;
  181. Ch = 3;
  182. if (p->Ptr[1] & 4)
  183. ++Ch; // alpha
  184. }
  185. else
  186. {
  187. if (p->Ptr[1] & 4)
  188. return NotSupported(p); //todo
  189. Video.Pixel.Flags |= PF_PALETTE|PF_GRAYSCALE;
  190. Ch = 1;
  191. }
  192. for (i=0;i<256;++i)
  193. Pal[i].v = CRGB(i,i,i);
  194. BytesPerRow = Ch * ((Video.Width * Video.Pixel.BitCount)>>3)+1;
  195. Left = BytesPerRow;
  196. Row = Video.Height;
  197. LastRow = NULL;
  198. Video.Pixel.BitCount *= Ch;
  199. DefaultPitch(&Video);
  200. if (!BufferAlloc(&p->Buffer,Video.Pitch*Video.Height,4096))
  201. return ERR_OUT_OF_MEMORY;
  202. memset(&Inflate,0,sizeof(Inflate));
  203.     if (inflateInit2(&Inflate, MAX_WBITS) != Z_OK)
  204. return ERR_OUT_OF_MEMORY;
  205. break;
  206. case FOURCCBE('P','L','T','E'):
  207. for (i=0;i<256 && Len>=3;++i,Len-=3,p->Ptr+=3)
  208. {
  209. Pal[i].c.r = p->Ptr[0];
  210. Pal[i].c.g = p->Ptr[1];
  211. Pal[i].c.b = p->Ptr[2];
  212. }
  213. break;
  214. case FOURCCBE('I','D','A','T'):
  215. if (!BytesPerRow || Row<=0)
  216. break;
  217. if (!EqVideo(&Video,&p->Codec.Out.Format.Format.Video))
  218. {
  219. if ((Video.Pixel.Flags & PF_PALETTE) && PacketFormatExtra(&p->Codec.Out.Format,sizeof(Pal)))
  220. {
  221. memcpy(p->Codec.Out.Format.Extra,Pal,sizeof(Pal));
  222. Video.Pixel.Palette = p->Codec.Out.Format.Extra;
  223. }
  224. p->Codec.In.Format.Format.Video.Width = Video.Width;
  225. p->Codec.In.Format.Format.Video.Height = Video.Height;
  226. p->Codec.Out.Format.Format.Video = Video;
  227. ConnectionUpdate(&p->Codec.Node,CODEC_OUTPUT,p->Codec.Out.Pin.Node,p->Codec.Out.Pin.No);
  228. }
  229. Inflate.next_in = (Bytef*)p->Ptr;
  230. Inflate.avail_in = Len;
  231. Inflate.next_out = p->Buffer.Data + p->Buffer.WritePos;
  232. Inflate.avail_out = Left;
  233. do
  234. {
  235. if (Inflate.avail_out<=0)
  236. {
  237. uint8_t* CurrRow = p->Buffer.Data + p->Buffer.WritePos - BytesPerRow;
  238. Filter(CurrRow[0],CurrRow+1,LastRow,CurrRow,Ch,BytesPerRow-1);
  239. LastRow = CurrRow;
  240. p->Buffer.WritePos += Video.Pitch - BytesPerRow;
  241. Inflate.next_out += Video.Pitch - BytesPerRow;
  242. Inflate.avail_out = Left = BytesPerRow;
  243. if (--Row<=0)
  244. break;
  245. }
  246. if (Inflate.avail_in<=0)
  247. break;
  248. i = inflate(&Inflate, Z_SYNC_FLUSH);
  249. p->Buffer.WritePos += Left - Inflate.avail_out;
  250. Left = Inflate.avail_out;
  251. if (i==Z_STREAM_END)
  252. Inflate.avail_in = 0;
  253. } while (i>=0);
  254. break;
  255. case FOURCCBE('I','E','N','D'):
  256. Next = PtrEnd;
  257. break;
  258. }
  259. p->Ptr = Next;
  260. }
  261. if (BytesPerRow)
  262. inflateEnd(&Inflate);
  263. if (p->Buffer.WritePos<=0)
  264. return ERR_INVALID_DATA;
  265. p->Codec.Packet.RefTime = Packet->RefTime;
  266. p->Codec.Packet.Length = p->Buffer.WritePos;
  267. p->Codec.Packet.Data[0] = p->Buffer.Data;
  268. return ERR_NONE;
  269. }
  270. static int Resend(png* p)
  271. {
  272. int Result = ERR_INVALID_DATA;
  273. if (p->Buffer.WritePos)
  274. {
  275. packet Packet;
  276. flowstate State;
  277. State.CurrTime = TIME_RESEND;
  278. State.DropLevel = 0;
  279. memset(&Packet,0,sizeof(Packet));
  280. Packet.RefTime = TIME_UNKNOWN;
  281. Packet.Length = p->Buffer.WritePos;
  282. Packet.Data[0] = p->Buffer.Data;
  283. Result = p->Codec.Out.Process(p->Codec.Out.Pin.Node,&Packet,&State);
  284. }
  285. return Result;
  286. }
  287. static int Flush(png* p)
  288. {
  289. BufferDrop(&p->Buffer);
  290. return ERR_NONE;
  291. }
  292. static int Create(png* p)
  293. {
  294. p->Codec.Process = (packetprocess)Process;
  295. p->Codec.UpdateInput = (nodefunc)UpdateInput;
  296. p->Codec.ReSend = (nodefunc)Resend;
  297. p->Codec.Flush = (nodefunc)Flush;
  298. return ERR_NONE;
  299. }
  300. static const nodedef PNG =
  301. {
  302. sizeof(png),
  303. PNG_ID,
  304. CODEC_CLASS,
  305. PRI_DEFAULT,
  306. (nodecreate)Create,
  307. NULL,
  308. };
  309. //-------------------------------------------------------------------------------------------
  310. static const nodedef PNGFile =
  311. {
  312. 0, // parent size
  313. PNG_FILE_ID,
  314. RAWIMAGE_CLASS,
  315. PRI_DEFAULT,
  316. };
  317. //---------------------------------------------------------------------------------------------
  318. void PNG_Init()
  319. {
  320. NodeRegisterClass(&PNG);
  321. NodeRegisterClass(&PNGFile);
  322. }
  323. void PNG_Done()
  324. {
  325. NodeUnRegisterClass(PNG_ID);
  326. NodeUnRegisterClass(PNG_FILE_ID);
  327. }