- Timestamp:
- Nov 6, 2009 3:53:06 PM (15 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/DisplayImpl.cpp
r24407 r24457 43 43 44 44 #include <VBox/com/array.h> 45 #include <png.h> 45 46 46 47 /** … … 116 117 #define sSSMDisplayVer 0x00010001 117 118 119 #define kMaxSizePNG 1024 120 #define kMaxSizeThumbnail 64 121 118 122 /** 119 123 * Save thumbnail and screenshot of the guest screen. … … 131 135 if (cx > cy) 132 136 { 133 cxThumbnail = 64;134 cyThumbnail = ( 64* cy) / cx;137 cxThumbnail = kMaxSizeThumbnail; 138 cyThumbnail = (kMaxSizeThumbnail * cy) / cx; 135 139 } 136 140 else 137 141 { 138 cyThumbnail = 64;139 cxThumbnail = ( 64* cx) / cy;142 cyThumbnail = kMaxSizeThumbnail; 143 cxThumbnail = (kMaxSizeThumbnail * cx) / cy; 140 144 } 141 145 … … 176 180 } 177 181 182 typedef struct PNGWriteCtx 183 { 184 uint8_t *pu8PNG; 185 uint32_t cbPNG; 186 uint32_t cbAllocated; 187 int rc; 188 } PNGWriteCtx; 189 190 static void PNGAPI png_write_data_fn(png_structp png_ptr, png_bytep p, png_size_t cb) 191 { 192 PNGWriteCtx *pCtx = (PNGWriteCtx *)png_get_io_ptr(png_ptr); 193 LogFlowFunc(("png_ptr %p, p %p, cb %d, pCtx %p\n", png_ptr, p, cb, pCtx)); 194 195 if (pCtx && RT_SUCCESS(pCtx->rc)) 196 { 197 if (pCtx->cbAllocated - pCtx->cbPNG < cb) 198 { 199 uint32_t cbNew = pCtx->cbPNG + (uint32_t)cb; 200 cbNew = RT_ALIGN_32(cbNew, 4096) + 4096; 201 202 void *pNew = RTMemRealloc(pCtx->pu8PNG, cbNew); 203 if (!pNew) 204 { 205 pCtx->rc = VERR_NO_MEMORY; 206 return; 207 } 208 209 pCtx->pu8PNG = (uint8_t *)pNew; 210 pCtx->cbAllocated = cbNew; 211 } 212 213 memcpy(pCtx->pu8PNG + pCtx->cbPNG, p, cb); 214 pCtx->cbPNG += cb; 215 } 216 } 217 218 static void PNGAPI png_output_flush_fn(png_structp png_ptr) 219 { 220 NOREF(png_ptr); 221 /* Do nothing. */ 222 } 223 178 224 static int displayMakePNG(uint8_t *pu8Data, uint32_t cx, uint32_t cy, 179 225 uint8_t **ppu8PNG, uint32_t *pcbPNG, uint32_t *pcxPNG, uint32_t *pcyPNG) 180 226 { 181 227 int rc = VINF_SUCCESS; 228 229 uint8_t *pu8Bitmap = NULL; 230 uint32_t cbBitmap = 0; 231 uint32_t cxBitmap = 0; 232 uint32_t cyBitmap = 0; 233 234 if (cx < kMaxSizePNG && cy < kMaxSizePNG) 235 { 236 /* Save unscaled screenshot. */ 237 pu8Bitmap = pu8Data; 238 cbBitmap = cx * 4 * cy; 239 cxBitmap = cx; 240 cyBitmap = cy; 241 } 242 else 243 { 244 /* Large screenshot, scale. */ 245 if (cx > cy) 246 { 247 cxBitmap = kMaxSizePNG; 248 cyBitmap = (kMaxSizePNG * cy) / cx; 249 } 250 else 251 { 252 cyBitmap = kMaxSizePNG; 253 cxBitmap = (kMaxSizePNG * cx) / cy; 254 } 255 256 cbBitmap = cxBitmap * 4 * cyBitmap; 257 258 pu8Bitmap = (uint8_t *)RTMemAlloc(cbBitmap); 259 260 if (pu8Bitmap) 261 { 262 uint8_t *dst = pu8Bitmap; 263 uint8_t *src = pu8Data; 264 int dstX = 0; 265 int dstY = 0; 266 int srcX = 0; 267 int srcY = 0; 268 int dstW = cxBitmap; 269 int dstH = cyBitmap; 270 int srcW = cx; 271 int srcH = cy; 272 gdImageCopyResampled (dst, 273 src, 274 dstX, dstY, 275 srcX, srcY, 276 dstW, dstH, srcW, srcH); 277 } 278 else 279 { 280 rc = VERR_NO_MEMORY; 281 } 282 } 283 284 LogFlowFunc(("%dx%d -> %dx%d\n", cx, cy, cxBitmap, cyBitmap)); 285 286 if (RT_SUCCESS(rc)) 287 { 288 png_bytep *row_pointers = (png_bytep *)RTMemAlloc(cyBitmap * sizeof(png_bytep)); 289 if (row_pointers) 290 { 291 png_infop info_ptr = NULL; 292 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 293 png_voidp_NULL, /* error/warning context pointer */ 294 png_error_ptr_NULL /* error function */, 295 png_error_ptr_NULL /* warning function */); 296 if (png_ptr) 297 { 298 info_ptr = png_create_info_struct(png_ptr); 299 if (info_ptr) 300 { 301 if (!setjmp(png_jmpbuf(png_ptr))) 302 { 303 PNGWriteCtx ctx; 304 ctx.pu8PNG = NULL; 305 ctx.cbPNG = 0; 306 ctx.cbAllocated = 0; 307 ctx.rc = VINF_SUCCESS; 308 309 png_set_write_fn(png_ptr, 310 (voidp)&ctx, 311 png_write_data_fn, 312 png_output_flush_fn); 313 314 png_set_IHDR(png_ptr, info_ptr, 315 cxBitmap, cyBitmap, 316 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, 317 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); 318 319 png_bytep row_pointer = (png_bytep)pu8Bitmap; 320 unsigned i = 0; 321 for (; i < cyBitmap; i++, row_pointer += cxBitmap * 4) 322 { 323 row_pointers[i] = row_pointer; 324 } 325 png_set_rows(png_ptr, info_ptr, &row_pointers[0]); 326 327 png_write_info(png_ptr, info_ptr); 328 png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); 329 png_set_bgr(png_ptr); 330 331 if (info_ptr->valid & PNG_INFO_IDAT) 332 png_write_image(png_ptr, info_ptr->row_pointers); 333 334 png_write_end(png_ptr, info_ptr); 335 336 rc = ctx.rc; 337 338 if (RT_SUCCESS(rc)) 339 { 340 *ppu8PNG = ctx.pu8PNG; 341 *pcbPNG = ctx.cbPNG; 342 *pcxPNG = cxBitmap; 343 *pcyPNG = cyBitmap; 344 LogFlowFunc(("PNG %d bytes, bitmap %d bytes\n", ctx.cbPNG, cbBitmap)); 345 } 346 } 347 else 348 { 349 rc = VERR_GENERAL_FAILURE; /* Something within libpng. */ 350 } 351 } 352 else 353 { 354 rc = VERR_NO_MEMORY; 355 } 356 357 png_destroy_write_struct(&png_ptr, info_ptr? &info_ptr: png_infopp_NULL); 358 } 359 else 360 { 361 rc = VERR_NO_MEMORY; 362 } 363 364 RTMemFree(row_pointers); 365 } 366 else 367 { 368 rc = VERR_NO_MEMORY; 369 } 370 } 371 372 if (pu8Bitmap && pu8Bitmap != pu8Data) 373 { 374 RTMemFree(pu8Bitmap); 375 } 376 182 377 return rc; 378 183 379 } 184 380 … … 188 384 Display *that = static_cast<Display*>(pvUser); 189 385 190 /* 32bpp small image with maximum dimension = 64 pixels. */386 /* 32bpp small RGB image. */ 191 387 uint8_t *pu8Thumbnail = NULL; 192 388 uint32_t cbThumbnail = 0; … … 194 390 uint32_t cyThumbnail = 0; 195 391 196 /* PNG screenshot with maximum dimension = 1024 pixels. */392 /* PNG screenshot. */ 197 393 uint8_t *pu8PNG = NULL; 198 394 uint32_t cbPNG = 0; … … 228 424 } 229 425 230 /* Regardless of rc, save what is available */ 231 232 SSMR3PutU32(pSSM, cbThumbnail); 426 /* Regardless of rc, save what is available: 427 * Data format: 428 * uint32_t cBlocks; 429 * [blocks] 430 * 431 * Each block is: 432 * uint32_t cbBlock; if 0 - no 'block data'. 433 * uint32_t typeOfBlock; 0 - 32bpp RGB bitmap, 1 - PNG, ignored if 'cbBlock' is 0. 434 * [block data] 435 * 436 * Block data for bitmap and PNG: 437 * uint32_t cx; 438 * uint32_t cy; 439 * [image data] 440 */ 441 SSMR3PutU32(pSSM, 2); /* Write thumbnail and PNG screenshot. */ 442 443 /* First block. */ 444 SSMR3PutU32(pSSM, cbThumbnail + 2 * sizeof (uint32_t)); 445 SSMR3PutU32(pSSM, 0); /* Block type: thumbnail. */ 233 446 234 447 if (cbThumbnail) … … 239 452 } 240 453 241 SSMR3PutU32(pSSM, cbPNG); 454 /* Second block. */ 455 SSMR3PutU32(pSSM, cbPNG + 2 * sizeof (uint32_t)); 456 SSMR3PutU32(pSSM, 1); /* Block type: png. */ 242 457 243 458 if (cbPNG) … … 250 465 RTMemFree(pu8PNG); 251 466 RTMemFree(pu8Thumbnail); 467 } 468 469 DECLCALLBACK(int) 470 Display::displaySSMLoadScreenshot(PSSMHANDLE pSSM, void *pvUser, uint32_t uVersion, uint32_t uPass) 471 { 472 Display *that = static_cast<Display*>(pvUser); 473 474 if (uVersion != sSSMDisplayScreenshotVer) 475 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION; 476 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass); 477 478 /* Skip data. */ 479 uint32_t cBlocks; 480 int rc = SSMR3GetU32(pSSM, &cBlocks); 481 AssertRCReturn(rc, rc); 482 483 for (uint32_t i = 0; i < cBlocks; i++) 484 { 485 uint32_t cbBlock; 486 rc = SSMR3GetU32(pSSM, &cbBlock); 487 AssertRCBreak(rc); 488 489 uint32_t typeOfBlock; 490 rc = SSMR3GetU32(pSSM, &typeOfBlock); 491 AssertRCBreak(rc); 492 493 LogFlowFunc(("[%d] type %d, size %d bytes\n", i, typeOfBlock, cbBlock)); 494 495 if (cbBlock != 0) 496 { 497 rc = SSMR3Skip(pSSM, cbBlock); 498 AssertRCBreak(rc); 499 } 500 } 501 502 return rc; 252 503 } 253 504 … … 420 671 NULL, NULL, NULL, 421 672 NULL, displaySSMSaveScreenshot, NULL, 422 NULL, NULL, NULL, this);673 NULL, displaySSMLoadScreenshot, NULL, this); 423 674 424 675 AssertRCReturn(rc, rc); -
trunk/src/VBox/Main/Makefile.kmk
r24373 r24457 525 525 DLLS += VBoxC 526 526 VBoxC_TEMPLATE = VBOXMAINCOMP 527 VBoxC_SDKS = VBOX_LIBPNG VBOX_ZLIB 527 528 VBoxC_DEFS = \ 528 529 IN_RING3 \ -
trunk/src/VBox/Main/include/DisplayImpl.h
r24405 r24457 296 296 297 297 298 static DECLCALLBACK(void) displaySSMSaveScreenshot(PSSMHANDLE pSSM, void *pvUser); 299 static DECLCALLBACK(int) displaySSMLoadScreenshot(PSSMHANDLE pSSM, void *pvUser, uint32_t uVersion, uint32_t uPass); 298 300 static DECLCALLBACK(void) displaySSMSave(PSSMHANDLE pSSM, void *pvUser); 299 301 static DECLCALLBACK(int) displaySSMLoad(PSSMHANDLE pSSM, void *pvUser, uint32_t uVersion, uint32_t uPass); 300 static DECLCALLBACK(void) displaySSMSaveScreenshot(PSSMHANDLE pSSM, void *pvUser);301 302 302 303 const ComObjPtr<Console, ComWeakRef> mParent;
Note:
See TracChangeset
for help on using the changeset viewer.