VirtualBox

source: vbox/trunk/src/VBox/Main/src-all/DisplayPNGUtil.cpp@ 85238

Last change on this file since 85238 was 85121, checked in by vboxsync, 4 years ago

iprt/cdefs.h: Refactored the typedef use of DECLCALLBACK as well as DECLCALLBACKMEMBER to wrap the whole expression, similar to the DECLR?CALLBACKMEMBER macros. This allows adding a throw() at the end when compiling with the VC++ compiler to indicate that the callbacks won't throw anything, so we can stop supressing the C5039 warning about passing functions that can potential throw C++ exceptions to extern C code that can't necessarily cope with such (unwind,++). Introduced a few _EX variations that allows specifying different/no calling convention too, as that's handy when dynamically resolving host APIs. Fixed numerous places missing DECLCALLBACK and such. Left two angry @todos regarding use of CreateThread. bugref:9794

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.1 KB
Line 
1/* $Id: DisplayPNGUtil.cpp 85121 2020-07-08 19:33:26Z vboxsync $ */
2/** @file
3 * PNG utilities
4 */
5
6/*
7 * Copyright (C) 2010-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#define LOG_GROUP LOG_GROUP_MAIN_DISPLAY
19#include "DisplayImpl.h"
20
21#include <iprt/alloc.h>
22
23#include <png.h>
24
25#define kMaxSizePNG 1024
26
27typedef struct PNGWriteCtx
28{
29 uint8_t *pu8PNG;
30 uint32_t cbPNG;
31 uint32_t cbAllocated;
32 int rc;
33} PNGWriteCtx;
34
35static void PNGAPI png_write_data_fn(png_structp png_ptr, png_bytep p, png_size_t cb) RT_NOTHROW_DEF
36{
37 PNGWriteCtx *pCtx = (PNGWriteCtx *)png_get_io_ptr(png_ptr);
38 LogFlowFunc(("png_ptr %p, p %p, cb %d, pCtx %p\n", png_ptr, p, cb, pCtx));
39
40 if (pCtx && RT_SUCCESS(pCtx->rc))
41 {
42 if (pCtx->cbAllocated - pCtx->cbPNG < cb)
43 {
44 uint32_t cbNew = pCtx->cbPNG + (uint32_t)cb;
45 AssertReturnVoidStmt(cbNew > pCtx->cbPNG && cbNew <= _1G, pCtx->rc = VERR_TOO_MUCH_DATA);
46 cbNew = RT_ALIGN_32(cbNew, 4096) + 4096;
47
48 void *pNew = RTMemRealloc(pCtx->pu8PNG, cbNew);
49 if (!pNew)
50 {
51 pCtx->rc = VERR_NO_MEMORY;
52 return;
53 }
54
55 pCtx->pu8PNG = (uint8_t *)pNew;
56 pCtx->cbAllocated = cbNew;
57 }
58
59 memcpy(pCtx->pu8PNG + pCtx->cbPNG, p, cb);
60 pCtx->cbPNG += (uint32_t)cb;
61 }
62}
63
64static void PNGAPI png_output_flush_fn(png_structp png_ptr) RT_NOTHROW_DEF
65{
66 NOREF(png_ptr);
67 /* Do nothing. */
68}
69
70int DisplayMakePNG(uint8_t *pu8Data, uint32_t cx, uint32_t cy,
71 uint8_t **ppu8PNG, uint32_t *pcbPNG, uint32_t *pcxPNG, uint32_t *pcyPNG,
72 uint8_t fLimitSize)
73{
74 int rc = VINF_SUCCESS;
75
76 uint8_t * volatile pu8Bitmap = NULL; /* gcc setjmp warning */
77 uint32_t volatile cbBitmap = 0; /* gcc setjmp warning */
78 uint32_t volatile cxBitmap = 0; /* gcc setjmp warning */
79 uint32_t volatile cyBitmap = 0; /* gcc setjmp warning */
80
81 if (!fLimitSize || (cx < kMaxSizePNG && cy < kMaxSizePNG))
82 {
83 /* Save unscaled screenshot. */
84 pu8Bitmap = pu8Data;
85 cbBitmap = cx * 4 * cy;
86 cxBitmap = cx;
87 cyBitmap = cy;
88 }
89 else
90 {
91 /* Large screenshot, scale. */
92 if (cx > cy)
93 {
94 cxBitmap = kMaxSizePNG;
95 cyBitmap = (kMaxSizePNG * cy) / cx;
96 }
97 else
98 {
99 cyBitmap = kMaxSizePNG;
100 cxBitmap = (kMaxSizePNG * cx) / cy;
101 }
102
103 cbBitmap = cxBitmap * 4 * cyBitmap;
104
105 pu8Bitmap = (uint8_t *)RTMemAlloc(cbBitmap);
106
107 if (pu8Bitmap)
108 {
109 uint8_t *dst = pu8Bitmap;
110 uint8_t *src = pu8Data;
111 int dstW = cxBitmap;
112 int dstH = cyBitmap;
113 int srcW = cx;
114 int srcH = cy;
115 int iDeltaLine = cx * 4;
116
117 BitmapScale32 (dst,
118 dstW, dstH,
119 src,
120 iDeltaLine,
121 srcW, srcH);
122 }
123 else
124 {
125 rc = VERR_NO_MEMORY;
126 }
127 }
128
129 LogFlowFunc(("%dx%d -> %dx%d\n", cx, cy, cxBitmap, cyBitmap));
130
131 if (RT_SUCCESS(rc))
132 {
133 png_bytep *row_pointers = (png_bytep *)RTMemAlloc(cyBitmap * sizeof(png_bytep));
134 if (row_pointers)
135 {
136 png_infop info_ptr = NULL;
137 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
138 (png_voidp)NULL, /* error/warning context pointer */
139 (png_error_ptr)NULL, /* error function */
140 (png_error_ptr)NULL /* warning function */);
141 if (png_ptr)
142 {
143 info_ptr = png_create_info_struct(png_ptr);
144 if (info_ptr)
145 {
146#if RT_MSC_PREREQ(RT_MSC_VER_VC140)
147#pragma warning(push,3)
148 if (!setjmp(png_jmpbuf(png_ptr)))
149#pragma warning(pop)
150#else
151 if (!setjmp(png_jmpbuf(png_ptr)))
152#endif
153 {
154 PNGWriteCtx ctx;
155 ctx.pu8PNG = NULL;
156 ctx.cbPNG = 0;
157 ctx.cbAllocated = 0;
158 ctx.rc = VINF_SUCCESS;
159
160 png_set_write_fn(png_ptr,
161 (png_voidp)&ctx,
162 png_write_data_fn,
163 png_output_flush_fn);
164
165 png_set_IHDR(png_ptr, info_ptr,
166 cxBitmap, cyBitmap,
167 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
168 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
169
170 png_bytep row_pointer = (png_bytep)pu8Bitmap;
171 unsigned i = 0;
172 for (; i < cyBitmap; i++, row_pointer += cxBitmap * 4)
173 {
174 row_pointers[i] = row_pointer;
175 }
176 png_set_rows(png_ptr, info_ptr, &row_pointers[0]);
177
178 png_write_info(png_ptr, info_ptr);
179 png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
180 png_set_bgr(png_ptr);
181
182 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_IDAT))
183 png_write_image(png_ptr, png_get_rows(png_ptr, info_ptr));
184
185 png_write_end(png_ptr, info_ptr);
186
187 rc = ctx.rc;
188
189 if (RT_SUCCESS(rc))
190 {
191 *ppu8PNG = ctx.pu8PNG;
192 *pcbPNG = ctx.cbPNG;
193 *pcxPNG = cxBitmap;
194 *pcyPNG = cyBitmap;
195 LogFlowFunc(("PNG %d bytes, bitmap %d bytes\n", ctx.cbPNG, cbBitmap));
196 }
197 }
198 else
199 {
200 rc = VERR_GENERAL_FAILURE; /* Something within libpng. */
201 }
202 }
203 else
204 {
205 rc = VERR_NO_MEMORY;
206 }
207
208 png_destroy_write_struct(&png_ptr, info_ptr ? &info_ptr
209 : (png_infopp)NULL);
210 }
211 else
212 {
213 rc = VERR_NO_MEMORY;
214 }
215
216 RTMemFree(row_pointers);
217 }
218 else
219 {
220 rc = VERR_NO_MEMORY;
221 }
222 }
223
224 if (pu8Bitmap && pu8Bitmap != pu8Data)
225 {
226 RTMemFree(pu8Bitmap);
227 }
228
229 return rc;
230
231}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette