VirtualBox

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

Last change on this file since 101505 was 98103, checked in by vboxsync, 2 years ago

Copyright year updates by scm.

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