Changeset 14770

Show
Ignore:
Timestamp:
06/26/08 15:50:06 (5 months ago)
Author:
rouault
Message:

JPEG driver : add support for reading images in CMYK and YCbCrK color spaces (#2443)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/gdal/frmts/jpeg/frmt_jpeg.html

    r13801 r14770  
    1212band (RGB) datasets with Byte valued bands.<p> 
    1313 
     14The driver will automatically convert images whose color space is YCbCr, CMYK or 
     15YCbCrK to RGB, unless GDAL_JPEG_TO_RGB is set to NO (YES is the default). When 
     16color space translation to RGB is done, the source color space is indicated in the 
     17SOURCE_COLOR_SPACE metedata of the IMAGE_STRUCTURE domain.<p> 
     18 
    1419There is currently no support for georeferencing information or metadata for 
    1520JPEG files. But if an ESRI world file exists with the .jgw, .jpgw/.jpegw or .wld suffixes, 
    1621it will be read and used to establish the geotransform for the image. Overviews 
    1722can be built for JPEG files as an external .ovr file.<p> 
     23 
     24The driver also supports the "zlib compressed mask appended to the file" approach 
     25used by a few data providers to add a bitmask to identify pixels that are not valid data. 
     26See <a href="http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask">RFC 15</a> for further details.<p> 
    1827 
    1928The GDAL JPEG Driver is built using the Independent JPEG Group's jpeg 
     
    2433 
    2534JPEG files are created using the "JPEG" driver code.  Only Byte band types 
    26 are supported, and only 1 and 3 band configurations.  JPEG file creation 
    27 is implemented by the batch (CreateCopy) method.   
     35are supported, and only 1 and 3 band (RGB) configurations.  JPEG file creation 
     36is implemented by the batch (CreateCopy) method. YCbCr, CMYK or YCbCrK colorspaces 
     37are not supported in creation. If the source dataset has a nodata mask, it will be 
     38appended as a zlib compressed mask to the JPEG file.<p> 
    2839 
    2940<ul> 
  • trunk/gdal/frmts/jpeg/jpgdataset.cpp

    r14740 r14770  
    114114    int    nCMaskSize; 
    115115 
     116    J_COLOR_SPACE eGDALColorSpace;   /* color space exposed by GDAL. Not necessarily the in_color_space nor */ 
     117                                     /* the out_color_space of JPEG library */ 
     118 
    116119  public: 
    117120                 JPGDataset(); 
     
    740743                       nXSize ); 
    741744#else 
    742         GDALCopyWords( poGDS->pabyScanline + (nBand-1) * nWordSize,  
    743                        eDataType, nWordSize * 3,  
    744                        pImage, eDataType, nWordSize,  
    745                        nXSize ); 
     745        if (poGDS->eGDALColorSpace == JCS_RGB && 
     746            poGDS->sDInfo.out_color_space == JCS_CMYK) 
     747        { 
     748            CPLAssert(eDataType == GDT_Byte); 
     749            int i; 
     750            if (nBand == 1) 
     751            { 
     752                for(i=0;i<nXSize;i++) 
     753                { 
     754                    int C = poGDS->pabyScanline[i * 4 + 0]; 
     755                    int K = poGDS->pabyScanline[i * 4 + 3]; 
     756                    ((GByte*)pImage)[i] = (C * K) / 255; 
     757                } 
     758            } 
     759            else  if (nBand == 2) 
     760            { 
     761                for(i=0;i<nXSize;i++) 
     762                { 
     763                    int M = poGDS->pabyScanline[i * 4 + 1]; 
     764                    int K = poGDS->pabyScanline[i * 4 + 3]; 
     765                    ((GByte*)pImage)[i] = (M * K) / 255; 
     766                } 
     767            } 
     768            else if (nBand == 3) 
     769            { 
     770                for(i=0;i<nXSize;i++) 
     771                { 
     772                    int Y = poGDS->pabyScanline[i * 4 + 2]; 
     773                    int K = poGDS->pabyScanline[i * 4 + 3]; 
     774                    ((GByte*)pImage)[i] = (Y * K) / 255; 
     775                } 
     776            } 
     777        } 
     778        else 
     779        { 
     780            GDALCopyWords( poGDS->pabyScanline + (nBand-1) * nWordSize,  
     781                        eDataType, nWordSize * poGDS->GetRasterCount(),  
     782                        pImage, eDataType, nWordSize,  
     783                        nXSize ); 
     784        } 
    746785#endif 
    747786    } 
     
    750789/*      Forceably load the other bands associated with this scanline.   */ 
    751790/* -------------------------------------------------------------------- */ 
    752     if( poGDS->GetRasterCount() == 3 && nBand == 1 ) 
     791    if( nBand == 1 ) 
    753792    { 
    754793        GDALRasterBlock *poBlock; 
    755794 
    756         poBlock =  
    757             poGDS->GetRasterBand(2)->GetLockedBlockRef(nBlockXOff,nBlockYOff); 
    758         poBlock->DropLock(); 
    759  
    760         poBlock =  
    761             poGDS->GetRasterBand(3)->GetLockedBlockRef(nBlockXOff,nBlockYOff); 
    762         poBlock->DropLock(); 
    763     } 
     795        int iBand; 
     796        for(iBand = 2; iBand <= poGDS->GetRasterCount() ; iBand++) 
     797        { 
     798            poBlock =  
     799                poGDS->GetRasterBand(iBand)->GetLockedBlockRef(nBlockXOff,nBlockYOff); 
     800            poBlock->DropLock(); 
     801        } 
     802    } 
     803 
    764804 
    765805    return CE_None; 
     
    773813 
    774814{ 
    775     if( poGDS->nBands == 1
     815    if( poGDS->eGDALColorSpace == JCS_GRAYSCALE
    776816        return GCI_GrayIndex; 
    777817 
    778     else if( nBand == 1 ) 
    779         return GCI_RedBand; 
    780  
    781     else if( nBand == 2 ) 
    782         return GCI_GreenBand; 
    783  
    784     else  
    785         return GCI_BlueBand; 
     818    else if( poGDS->eGDALColorSpace == JCS_RGB) 
     819    { 
     820        if ( nBand == 1 ) 
     821            return GCI_RedBand; 
     822 
     823        else if( nBand == 2 ) 
     824            return GCI_GreenBand; 
     825 
     826        else  
     827            return GCI_BlueBand; 
     828    } 
     829    else if( poGDS->eGDALColorSpace == JCS_CMYK) 
     830    { 
     831        if ( nBand == 1 ) 
     832            return GCI_CyanBand; 
     833 
     834        else if( nBand == 2 ) 
     835            return GCI_MagentaBand; 
     836 
     837        else if ( nBand == 3 ) 
     838            return GCI_YellowBand; 
     839 
     840        else 
     841            return GCI_BlackBand; 
     842    } 
     843    else if( poGDS->eGDALColorSpace == JCS_YCbCr || 
     844             poGDS->eGDALColorSpace == JCS_YCCK) 
     845    { 
     846        if ( nBand == 1 ) 
     847            return GCI_YCbCr_YBand; 
     848 
     849        else if( nBand == 2 ) 
     850            return GCI_YCbCr_CbBand; 
     851 
     852        else if ( nBand == 3 ) 
     853            return GCI_YCbCr_CrBand; 
     854 
     855        else 
     856            return GCI_BlackBand; 
     857    } 
     858    else 
     859    { 
     860        CPLAssert(0); 
     861        return GCI_Undefined; 
     862    } 
    786863} 
    787864 
     
    858935    pabyCMask = NULL; 
    859936    nCMaskSize = 0; 
     937 
     938    eGDALColorSpace = JCS_UNKNOWN; 
    860939} 
    861940 
     
    911990 
    912991    if( pabyScanline == NULL ) 
     992    { 
     993        int nJPEGBands = 0; 
     994        switch(sDInfo.out_color_space) 
     995        { 
     996            case JCS_GRAYSCALE: 
     997                nJPEGBands = 1; 
     998                break; 
     999            case JCS_RGB: 
     1000            case JCS_YCbCr: 
     1001                nJPEGBands = 3; 
     1002                break; 
     1003            case JCS_CMYK: 
     1004            case JCS_YCCK: 
     1005                nJPEGBands = 4; 
     1006                break; 
     1007 
     1008            default: 
     1009                CPLAssert(0); 
     1010        } 
     1011 
    9131012        pabyScanline = (GByte *) 
    914             CPLMalloc(GetRasterCount() * GetRasterXSize() * 2); 
     1013            CPLMalloc(nJPEGBands * GetRasterXSize() * 2); 
     1014    } 
    9151015 
    9161016    // setup to trap a fatal error. 
     
    11151215 
    11161216{ 
     1217    J_COLOR_SPACE colorSpace = sDInfo.out_color_space; 
     1218 
    11171219    jpeg_abort_decompress( &sDInfo ); 
    11181220    jpeg_destroy_decompress( &sDInfo ); 
     
    11321234    jpeg_read_header( &sDInfo, TRUE ); 
    11331235     
    1134     if( GetRasterCount() == 1 ) 
    1135         sDInfo.out_color_space = JCS_GRAYSCALE; 
    1136     else 
    1137         sDInfo.out_color_space = JCS_RGB; 
     1236    sDInfo.out_color_space = colorSpace; 
    11381237    nLoadedScanline = -1; 
    11391238    jpeg_start_decompress( &sDInfo ); 
     
    14571556    poDS->nRasterYSize = poDS->sDInfo.image_height; 
    14581557 
     1558    poDS->sDInfo.out_color_space = poDS->sDInfo.jpeg_color_space; 
     1559    poDS->eGDALColorSpace = poDS->sDInfo.jpeg_color_space; 
     1560 
    14591561    if( poDS->sDInfo.jpeg_color_space == JCS_GRAYSCALE ) 
    14601562    { 
    14611563        poDS->nBands = 1; 
    1462         poDS->sDInfo.out_color_space = JCS_GRAYSCALE; 
    1463     } 
    1464     else if( poDS->sDInfo.jpeg_color_space == JCS_RGB  
    1465              || poDS->sDInfo.jpeg_color_space == JCS_YCbCr ) 
     1564    } 
     1565    else if( poDS->sDInfo.jpeg_color_space == JCS_RGB ) 
    14661566    { 
    14671567        poDS->nBands = 3; 
    1468         poDS->sDInfo.out_color_space = JCS_RGB; 
     1568    } 
     1569    else if( poDS->sDInfo.jpeg_color_space == JCS_YCbCr ) 
     1570    { 
     1571        poDS->nBands = 3; 
     1572        if (CSLTestBoolean(CPLGetConfigOption("GDAL_JPEG_TO_RGB", "YES"))) 
     1573        { 
     1574            poDS->sDInfo.out_color_space = JCS_RGB; 
     1575            poDS->eGDALColorSpace = JCS_RGB; 
     1576            poDS->SetMetadataItem( "SOURCE_COLOR_SPACE", "YCbCr", "IMAGE_STRUCTURE" ); 
     1577        } 
     1578    } 
     1579    else if( poDS->sDInfo.jpeg_color_space == JCS_CMYK ) 
     1580    { 
     1581        if (CSLTestBoolean(CPLGetConfigOption("GDAL_JPEG_TO_RGB", "YES"))) 
     1582        { 
     1583            poDS->eGDALColorSpace = JCS_RGB; 
     1584            poDS->nBands = 3; 
     1585            poDS->SetMetadataItem( "SOURCE_COLOR_SPACE", "CMYK", "IMAGE_STRUCTURE" ); 
     1586        } 
     1587        else 
     1588        { 
     1589            poDS->nBands = 4; 
     1590        } 
     1591    } 
     1592    else if( poDS->sDInfo.jpeg_color_space == JCS_YCCK ) 
     1593    { 
     1594        if (CSLTestBoolean(CPLGetConfigOption("GDAL_JPEG_TO_RGB", "YES"))) 
     1595        { 
     1596            poDS->eGDALColorSpace = JCS_RGB; 
     1597            poDS->nBands = 3; 
     1598            poDS->SetMetadataItem( "SOURCE_COLOR_SPACE", "YCbCrK", "IMAGE_STRUCTURE" ); 
     1599        } 
     1600        else 
     1601        { 
     1602            poDS->nBands = 4; 
     1603        } 
     1604        /* libjpeg does the translation from YCrCbK -> CMYK internally */ 
     1605        /* and we'll do the translation to RGB in IReadBlock() */ 
     1606        poDS->sDInfo.out_color_space = JCS_CMYK; 
    14691607    } 
    14701608    else