VirtualBox

Changeset 24457 in vbox for trunk/src


Ignore:
Timestamp:
Nov 6, 2009 3:53:06 PM (15 years ago)
Author:
vboxsync
Message:

Put PNG screenshot to saved state (works but disabled).

Location:
trunk/src/VBox/Main
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/DisplayImpl.cpp

    r24407 r24457  
    4343
    4444#include <VBox/com/array.h>
     45#include <png.h>
    4546
    4647/**
     
    116117#define sSSMDisplayVer 0x00010001
    117118
     119#define kMaxSizePNG 1024
     120#define kMaxSizeThumbnail 64
     121
    118122/**
    119123 * Save thumbnail and screenshot of the guest screen.
     
    131135    if (cx > cy)
    132136    {
    133         cxThumbnail = 64;
    134         cyThumbnail = (64 * cy) / cx;
     137        cxThumbnail = kMaxSizeThumbnail;
     138        cyThumbnail = (kMaxSizeThumbnail * cy) / cx;
    135139    }
    136140    else
    137141    {
    138         cyThumbnail = 64;
    139         cxThumbnail = (64 * cx) / cy;
     142        cyThumbnail = kMaxSizeThumbnail;
     143        cxThumbnail = (kMaxSizeThumbnail * cx) / cy;
    140144    }
    141145
     
    176180}
    177181
     182typedef struct PNGWriteCtx
     183{
     184    uint8_t *pu8PNG;
     185    uint32_t cbPNG;
     186    uint32_t cbAllocated;
     187    int rc;
     188} PNGWriteCtx;
     189
     190static 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
     218static void PNGAPI png_output_flush_fn(png_structp png_ptr)
     219{
     220    NOREF(png_ptr);
     221    /* Do nothing. */
     222}
     223
    178224static int displayMakePNG(uint8_t *pu8Data, uint32_t cx, uint32_t cy,
    179225                          uint8_t **ppu8PNG, uint32_t *pcbPNG, uint32_t *pcxPNG, uint32_t *pcyPNG)
    180226{
    181227    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
    182377    return rc;
     378
    183379}
    184380
     
    188384    Display *that = static_cast<Display*>(pvUser);
    189385
    190     /* 32bpp small image with maximum dimension = 64 pixels. */
     386    /* 32bpp small RGB image. */
    191387    uint8_t *pu8Thumbnail = NULL;
    192388    uint32_t cbThumbnail = 0;
     
    194390    uint32_t cyThumbnail = 0;
    195391
    196     /* PNG screenshot with maximum dimension = 1024 pixels. */
     392    /* PNG screenshot. */
    197393    uint8_t *pu8PNG = NULL;
    198394    uint32_t cbPNG = 0;
     
    228424    }
    229425
    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. */
    233446
    234447    if (cbThumbnail)
     
    239452    }
    240453
    241     SSMR3PutU32(pSSM, cbPNG);
     454    /* Second block. */
     455    SSMR3PutU32(pSSM, cbPNG + 2 * sizeof (uint32_t));
     456    SSMR3PutU32(pSSM, 1); /* Block type: png. */
    242457
    243458    if (cbPNG)
     
    250465    RTMemFree(pu8PNG);
    251466    RTMemFree(pu8Thumbnail);
     467}
     468
     469DECLCALLBACK(int)
     470Display::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;
    252503}
    253504
     
    420671                               NULL, NULL, NULL,
    421672                               NULL, displaySSMSaveScreenshot, NULL,
    422                                NULL, NULL, NULL, this);
     673                               NULL, displaySSMLoadScreenshot, NULL, this);
    423674
    424675    AssertRCReturn(rc, rc);
  • trunk/src/VBox/Main/Makefile.kmk

    r24373 r24457  
    525525DLLS += VBoxC
    526526VBoxC_TEMPLATE = VBOXMAINCOMP
     527VBoxC_SDKS =  VBOX_LIBPNG VBOX_ZLIB
    527528VBoxC_DEFS = \
    528529        IN_RING3 \
  • trunk/src/VBox/Main/include/DisplayImpl.h

    r24405 r24457  
    296296
    297297
     298    static DECLCALLBACK(void)   displaySSMSaveScreenshot(PSSMHANDLE pSSM, void *pvUser);
     299    static DECLCALLBACK(int)    displaySSMLoadScreenshot(PSSMHANDLE pSSM, void *pvUser, uint32_t uVersion, uint32_t uPass);
    298300    static DECLCALLBACK(void)   displaySSMSave(PSSMHANDLE pSSM, void *pvUser);
    299301    static DECLCALLBACK(int)    displaySSMLoad(PSSMHANDLE pSSM, void *pvUser, uint32_t uVersion, uint32_t uPass);
    300     static DECLCALLBACK(void)   displaySSMSaveScreenshot(PSSMHANDLE pSSM, void *pvUser);
    301302
    302303    const ComObjPtr<Console, ComWeakRef> mParent;
Note: See TracChangeset for help on using the changeset viewer.

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