Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

542 lines
17 KiB

  1. #ifndef _COPYONWRITEBITMAP_HPP
  2. #define _COPYONWRITEBITMAP_HPP
  3. class CopyOnWriteBitmap : private CopyOnWrite
  4. {
  5. friend class GpBitmap;
  6. private:
  7. // Constructors
  8. CopyOnWriteBitmap(const WCHAR* filename);
  9. CopyOnWriteBitmap(IStream* stream);
  10. CopyOnWriteBitmap(INT width, INT height, PixelFormatID format);
  11. CopyOnWriteBitmap(INT width, INT height, PixelFormatID format, GpGraphics * graphics);
  12. CopyOnWriteBitmap(
  13. INT width,
  14. INT height,
  15. INT stride, // negative for bottom-up bitmaps
  16. PixelFormatID format,
  17. BYTE * scan0
  18. );
  19. CopyOnWriteBitmap(
  20. BITMAPINFO* gdiBitmapInfo,
  21. VOID* gdiBitmapData,
  22. BOOL ownBitmapData
  23. );
  24. CopyOnWriteBitmap(IDirectDrawSurface7 *surface);
  25. static VOID CheckValid(CopyOnWriteBitmap *& p)
  26. {
  27. if ((p == NULL) || (!p->IsValid()))
  28. {
  29. delete p;
  30. p = NULL;
  31. }
  32. }
  33. static CopyOnWriteBitmap * Create(const WCHAR* filename)
  34. {
  35. CopyOnWriteBitmap * newBitmap = new CopyOnWriteBitmap(filename);
  36. CheckValid(newBitmap);
  37. return newBitmap;
  38. }
  39. static CopyOnWriteBitmap * Create(IStream* stream)
  40. {
  41. CopyOnWriteBitmap * newBitmap = new CopyOnWriteBitmap(stream);
  42. CheckValid(newBitmap);
  43. return newBitmap;
  44. }
  45. static CopyOnWriteBitmap * Create(INT width, INT height, PixelFormatID format)
  46. {
  47. CopyOnWriteBitmap * newBitmap = new CopyOnWriteBitmap(width, height, format);
  48. CheckValid(newBitmap);
  49. return newBitmap;
  50. }
  51. static CopyOnWriteBitmap * Create(INT width, INT height, PixelFormatID format, GpGraphics * graphics)
  52. {
  53. CopyOnWriteBitmap * newBitmap = new CopyOnWriteBitmap(width, height, format, graphics);
  54. CheckValid(newBitmap);
  55. return newBitmap;
  56. }
  57. static CopyOnWriteBitmap * Create(
  58. INT width,
  59. INT height,
  60. INT stride, // negative for bottom-up bitmaps
  61. PixelFormatID format,
  62. BYTE * scan0
  63. )
  64. {
  65. CopyOnWriteBitmap * newBitmap = new CopyOnWriteBitmap(width, height, stride, format, scan0);
  66. CheckValid(newBitmap);
  67. return newBitmap;
  68. }
  69. static CopyOnWriteBitmap * Create(
  70. BITMAPINFO* gdiBitmapInfo,
  71. VOID* gdiBitmapData,
  72. BOOL ownBitmapData
  73. )
  74. {
  75. CopyOnWriteBitmap * newBitmap = new CopyOnWriteBitmap(gdiBitmapInfo, gdiBitmapData, ownBitmapData);
  76. CheckValid(newBitmap);
  77. return newBitmap;
  78. }
  79. static CopyOnWriteBitmap * Create(IDirectDrawSurface7 *surface)
  80. {
  81. CopyOnWriteBitmap * newBitmap = new CopyOnWriteBitmap(surface);
  82. CheckValid(newBitmap);
  83. return newBitmap;
  84. }
  85. CopyOnWriteBitmap*
  86. Clone(
  87. const GpRect* rect,
  88. PixelFormatID format = PixelFormat32bppPARGB
  89. ) const;
  90. virtual CopyOnWrite * Clone() const
  91. {
  92. return Clone(NULL, PixelFormatDontCare);
  93. }
  94. CopyOnWriteBitmap*
  95. CloneColorAdjusted(
  96. GpRecolor * recolor,
  97. ColorAdjustType type = ColorAdjustTypeDefault
  98. ) const;
  99. GpStatus
  100. GetEncoderParameterListSize(
  101. IN CLSID* clsidEncoder,
  102. OUT UINT* size
  103. );
  104. GpStatus
  105. GetEncoderParameterList(
  106. IN CLSID* clsidEncoder,
  107. IN UINT size,
  108. OUT EncoderParameters* pBuffer
  109. );
  110. GpStatus
  111. SaveToStream(
  112. IStream* stream,
  113. CLSID* clsidEncoder,
  114. EncoderParameters* encoderParams
  115. );
  116. GpStatus
  117. SaveToFile(
  118. const WCHAR* filename,
  119. CLSID* clsidEncoder,
  120. EncoderParameters* encoderParams
  121. );
  122. GpStatus
  123. DoSave(
  124. IStream* stream,
  125. const WCHAR* filename,
  126. CLSID* clsidEncoder,
  127. EncoderParameters* encoderParams
  128. );
  129. GpStatus
  130. SaveAdd(
  131. const EncoderParameters* encoderParams
  132. );
  133. GpStatus
  134. SaveAdd(
  135. CopyOnWriteBitmap* newBits,
  136. const EncoderParameters* encoderParams
  137. );
  138. // Dispose the bitmap object
  139. VOID Dispose()
  140. {
  141. if (InterlockedDecrement(&ObjRefCount) <= 0)
  142. {
  143. this->Release();
  144. }
  145. }
  146. // Get bitmap information
  147. VOID GetImageInfo(ImageInfo * imageInfo)
  148. {
  149. ASSERT(imageInfo != NULL);
  150. GpMemcpy(imageInfo, &SrcImageInfo, sizeof(ImageInfo));
  151. }
  152. CopyOnWriteBitmap* GetThumbnail(UINT thumbWidth, UINT thumbHeight,
  153. GetThumbnailImageAbort callback,
  154. VOID *callbackData);
  155. GpStatus GetFrameCount(const GUID* dimensionID,
  156. UINT* count) const;
  157. GpStatus GetFrameDimensionsCount(OUT UINT* count) const;
  158. GpStatus GetFrameDimensionsList(OUT GUID* dimensionIDs,
  159. IN UINT count) const;
  160. GpStatus SelectActiveFrame(const GUID* dimensionID,
  161. UINT frameIndex);
  162. GpStatus GetPalette(ColorPalette *palette, INT size);
  163. GpStatus SetPalette(ColorPalette *palette);
  164. INT GetPaletteSize();
  165. GpStatus GetTransparencyHint(DpTransparency* transparency);
  166. GpStatus SetTransparencyHint(DpTransparency transparency);
  167. GpStatus GetTransparencyFlags(DpTransparency* transparency,
  168. PixelFormatID loadFormat =PixelFormatDontCare,
  169. BYTE* minA = NULL,
  170. BYTE* maxA = NULL);
  171. // Property related functions
  172. GpStatus GetPropertyCount(UINT* numOfProperty);
  173. GpStatus GetPropertyIdList(UINT numOfProperty, PROPID* list);
  174. GpStatus GetPropertyItemSize(PROPID propId, UINT* size);
  175. GpStatus GetPropertyItem(PROPID propId,UINT propSize,
  176. PropertyItem* buffer);
  177. GpStatus GetPropertySize(UINT* totalBufferSize,UINT* numProperties);
  178. GpStatus GetAllPropertyItems(UINT totalBufferSize,
  179. UINT numProperties,
  180. PropertyItem* allItems);
  181. GpStatus RemovePropertyItem(PROPID propId);
  182. GpStatus SetPropertyItem(PropertyItem* item);
  183. // Check if the CopyOnWriteBitmap object is valid
  184. virtual BOOL IsValid() const
  185. {
  186. return (State != Invalid);
  187. }
  188. // Retrieve bitmap data
  189. GpStatus
  190. LockBits(
  191. const GpRect* rect,
  192. UINT flags,
  193. PixelFormatID pixelFormat,
  194. BitmapData* bmpdata,
  195. INT width = 0,
  196. INT height = 0
  197. ) const; // Does not change the image
  198. GpStatus
  199. UnlockBits(
  200. BitmapData* bmpdata,
  201. BOOL Destroy=FALSE
  202. ) const;
  203. // Get and set pixel on the bitmap.
  204. GpStatus GetPixel(INT x, INT y, ARGB *color);
  205. GpStatus SetPixel(INT x, INT y, ARGB color);
  206. // Derive an HDC for interop on top of the bitmap object
  207. HDC GetHdc();
  208. VOID ReleaseHdc(HDC hdc);
  209. // Serialization
  210. UINT GetDataSize() const;
  211. GpStatus GetData(IStream * stream) const;
  212. GpStatus SetData(const BYTE * dataBuffer, UINT size);
  213. GpStatus GetCompressedData(
  214. DpCompressedData * compressed_data,
  215. BOOL getJPEG = TRUE,
  216. BOOL getPNG = TRUE,
  217. HDC hdc = (HDC)NULL);
  218. GpStatus DeleteCompressedData(
  219. DpCompressedData * compressed_data) ;
  220. // Image transform
  221. GpStatus RotateFlip(
  222. RotateFlipType rfType
  223. );
  224. // Color adjust
  225. GpStatus ColorAdjust(
  226. GpRecolor * recolor,
  227. ColorAdjustType type
  228. );
  229. GpStatus
  230. ColorAdjust(
  231. GpRecolor * recolor,
  232. PixelFormatID pixfmt,
  233. DrawImageAbort callback,
  234. VOID *callbackData
  235. );
  236. GpStatus GetPixelFormatID(PixelFormatID* pixfmt);
  237. enum
  238. {
  239. Invalid = 0, // bitmap object is invalid
  240. ImageRef = 1, // contains a reference only (e.g. filename)
  241. ExtStream = 2, // contains a reference to a stream
  242. DecodedImg = 3, // contains a decoded image object,
  243. // but it's not decoded yet - name is misleading.
  244. MemBitmap = 4 // contains an in-memory bitmap object
  245. };
  246. GpStatus SetResolution(REAL xdpi, REAL ydpi);
  247. GpStatus
  248. PreDraw(
  249. INT numPoints,
  250. GpPointF *dstPoints,
  251. GpRectF *srcRect,
  252. INT numBitsPerPixel
  253. );
  254. // Interop:
  255. static GpStatus CreateFromHBITMAP(
  256. HBITMAP hbm,
  257. HPALETTE hpal,
  258. CopyOnWriteBitmap** bitmap
  259. );
  260. GpStatus CreateHBITMAP(HBITMAP *phbm, ARGB background);
  261. GpStatus Recolor(
  262. GpRecolor *recolor,
  263. CopyOnWriteBitmap **dstBitmap,
  264. DrawImageAbort callback,
  265. VOID *callbackData,
  266. GpRect *rect = NULL
  267. );
  268. GpStatus ICMFrontEnd(
  269. CopyOnWriteBitmap **dstBitmap,
  270. DrawImageAbort callback,
  271. VOID *callbackData,
  272. GpRect *rect = NULL
  273. );
  274. static GpStatus CreateFromHICON(
  275. HICON hicon,
  276. CopyOnWriteBitmap** bitmap
  277. );
  278. GpStatus CreateHICON(HICON *phicon);
  279. static GpStatus CreateFromResource(
  280. HINSTANCE hInstance,
  281. LPWSTR lpBitmapName,
  282. CopyOnWriteBitmap** bitmap
  283. );
  284. private:
  285. CopyOnWriteBitmap(GpMemoryBitmap* membmp);
  286. mutable INT State; // current state of the bitmap object
  287. mutable LONG ObjRefCount; // object reference count used for LockBits
  288. WCHAR* Filename;
  289. IStream* Stream;
  290. mutable GpDecodedImage* Img;
  291. mutable GpMemoryBitmap* Bmp;
  292. UINT CurrentFrameIndex; // Frame index, zero based
  293. VOID* cleanupBitmapData; // Bitmap(BITMAPINFO*, ...) ctor will
  294. // set this if dtor should cleanup buffer
  295. IImageEncoder* EncoderPtr; // Pointer to encoder pointer for saving
  296. // multi-frame images
  297. // Note: CopyOnWriteBitmap has to hold this pointer
  298. // and do the close later. This is because
  299. // 1) Both Bmp and Img will be destroied when
  300. // navigating among frames
  301. // 2) It is possible that sometime we call
  302. // Img->SaveAppend and sometime for
  303. // Bmp->SaveAppend, depends on if the frame is
  304. // dirty or not.
  305. // It make sense that 1 CopyOnWriteBitmap talks to 1
  306. // encoder at a time
  307. BOOL SpecialJPEGSave; // TRUE if do special lossless JPEG transform
  308. BOOL ICMConvert; // TRUE if we should do ICM on this bitmap
  309. // We need to know how to handle the page transform when it is set
  310. // to UnitDisplay. If Display is TRUE (which is the default), then
  311. // the page transform will be the identity, which is what we want
  312. // most of the time. The only exception is when the image is
  313. // derived from a non-display graphics.
  314. BOOL Display; // Set UnitDisplay to identity transform?
  315. REAL XDpiOverride; // if non-zero, replaces native dpi
  316. REAL YDpiOverride; // if non-zero, replaces native dpi
  317. // supports scan interface to CopyOnWriteBitmap
  318. // when drawing to bitmap via a Graphics
  319. mutable BOOL DirtyFlag; // TRUE if the image bits got modified
  320. ImageInfo SrcImageInfo; // Image info for the source image
  321. mutable PixelFormatID PixelFormatInMem;
  322. // Pixel format in the memory
  323. // For example, if the source image is 4 bpp, we
  324. // load it into memory as 32 PARGB. This
  325. // variable will be set to 32PARGB.
  326. mutable BOOL HasChangedRequiredPixelFormat;
  327. // Flag to remember if we have hacked the color
  328. // formats or not in LoadIntoMemory(). Then this
  329. // format will be restored in ICMFrontEnd() if
  330. // this flag is TRUE
  331. struct // Interop data (information used to return
  332. { // an HDC that can draw into this CopyOnWriteBitmap)
  333. HDC Hdc;
  334. HBITMAP Hbm;
  335. VOID* Bits;
  336. INT_PTR Stride;
  337. INT Width;
  338. INT Height;
  339. } InteropData;
  340. VOID FreeData(); // called by destructor
  341. // Destructor
  342. // We don't want apps to use delete operator directly.
  343. // Instead, they should use Dispose method so that
  344. // we can take care of reference counting.
  345. ~CopyOnWriteBitmap();
  346. // Initialize the bitmap object to its initial state
  347. VOID InitDefaults()
  348. {
  349. State = Invalid;
  350. ObjRefCount = 1;
  351. Filename = NULL;
  352. Stream = NULL;
  353. Img = NULL;
  354. Bmp = NULL;
  355. InteropData.Hdc = NULL;
  356. InteropData.Hbm = NULL;
  357. CurrentFrameIndex = 0;
  358. cleanupBitmapData = NULL;
  359. DirtyFlag = FALSE;
  360. XDpiOverride = 0.0f; // if non-zero, replaces native dpi
  361. YDpiOverride = 0.0f; // if non-zero, replaces native dpi
  362. ICMConvert = FALSE; // default is don't do ICM (it's slow)
  363. SpecialJPEGSave = FALSE;
  364. // We must always treat the bitmap as if it is a display so that
  365. // the default page transform (in a graphics constructed from
  366. // the image) is the identity. The only time we don't do this
  367. // is if the bitmap is contructed from a graphics that is not
  368. // associated with a display. In that case, we want the image
  369. // to inherit the display property from the graphics so that
  370. // drawing to the image and drawing to the original graphics
  371. // will work the same, i.e. will have a similar page transform.
  372. Display = TRUE;
  373. EncoderPtr = NULL;
  374. PixelFormatInMem = PixelFormatUndefined;
  375. HasChangedRequiredPixelFormat = FALSE;
  376. GpMemset(&SrcImageInfo, 0, sizeof(ImageInfo));
  377. }
  378. // Convert the pixel data of a bitmap object
  379. // to the specified format
  380. GpStatus ConvertFormat(PixelFormatID format,
  381. DrawImageAbort callback = NULL,
  382. VOID *callbackData = NULL
  383. );
  384. // Perform color adjustment by the lower level codec if it can do it
  385. GpStatus
  386. ColorAdjustByCodec(
  387. GpRecolor * recolor,
  388. DrawImageAbort callback,
  389. VOID *callbackData
  390. );
  391. // Set decode parameters for icons
  392. GpStatus
  393. SetIconParameters(
  394. INT numPoints,
  395. GpPointF *dstPoints,
  396. GpRectF *srcRect,
  397. INT numBitsPerPixel
  398. );
  399. CopyOnWriteBitmap()
  400. {
  401. InitDefaults();
  402. }
  403. // Dereference the stream or file pointer and promote this bitmap object
  404. // to at least DecodedImg state.
  405. GpStatus CopyOnWriteBitmap::DereferenceStream() const;
  406. // Load bitmap image into memory
  407. // width and height are the suggested width and height to decode into.
  408. // zero means use the source width and height.
  409. GpStatus LoadIntoMemory(
  410. PixelFormatID format = PixelFormat32bppPARGB,
  411. DrawImageAbort callback = NULL,
  412. VOID *callbackData = NULL,
  413. INT width = 0,
  414. INT height = 0
  415. ) const;
  416. VOID SetDirtyFlag(BOOL flag) const
  417. {
  418. DirtyFlag = flag;
  419. }
  420. BOOL IsDirty() const
  421. {
  422. return DirtyFlag;
  423. }
  424. VOID TerminateEncoder()
  425. {
  426. if ( EncoderPtr != NULL )
  427. {
  428. EncoderPtr->TerminateEncoder();
  429. EncoderPtr->Release();
  430. EncoderPtr = NULL;
  431. }
  432. }
  433. GpStatus ValidateMultiFrameSave();
  434. GpStatus ParseEncoderParameter(
  435. const EncoderParameters* encoderParams,
  436. BOOL* pfIsMultiFrameSave,
  437. BOOL* pfSpecialJPEG,
  438. RotateFlipType* rfType
  439. );
  440. GpStatus TransformThumbanil(
  441. CLSID* clsidEncoder,
  442. EncoderParameters* encoderParams,
  443. PropertyItem **ppOriginalItem
  444. );
  445. VOID CacheImageInfo(HRESULT hr);
  446. private:
  447. GpStatus SaveAppend(
  448. const EncoderParameters* encoderParams,
  449. IImageEncoder* EncoderPtr
  450. );
  451. };
  452. #endif