jsjpeg.js
/**
 * Decode all of the data blocks in the MCU. The MCU contains 1 or more data
 * blocks for each component. The number of data blocks per component is 
 * determined by the horizontal + vertical sampling factors of each component.
 * 
 * See A.2.3 for information about decoding interleaved data units.
 * 
 * @param {DataViewReader} reader Data source
 * @param {*} img Struct with information about the image, including frame + components
 * @param {*} scan 
 * @param {*} vMCU Vertical index of this MCU
 * @param {*} hMCU Horizontal index of this MCU
 */
Decode all of the data blocks in the MCU. The MCU contains 1 or more data
blocks for each component. The number of data blocks per component is
determined by the horizontal + vertical sampling factors of each component.

See A.2.3 for information about decoding interleaved data units.


Decode all of the data blocks in the MCU . The MCU contains 1 or more data blocks for each component . The number of data blocks per component is determined by the horizontal + vertical sampling factors of each component . See A . 2 . 3 for information about decoding interleaved data units .
function decodeMCU(reader, img, scan, vMCU, hMCU) {
     Also want to bolt on the ZZ tables to Component....time to make a component class?
    for (let i = 0; i < scan.orderedComponents.length; i++) {
        let component = scan.orderedComponents[i];
        let id = component.componentID;
         Find the component metadata in the scan so we can look up huff tables. Ugh so messy
        let dcTableID = 0;
        let acTableID = 0;
         for (sc of scan.components) {
        for (let j = 0; j < scan.components.length; j++) {
            let sc = scan.components[j];
            if (sc[0] === id) {
                dcTableID = sc[1];
                acTableID = sc[2];
                break;
            }
        }
        let dcTable = img.huffmanTables[0][dcTableID];     0 is DC table, 1 is AC table: B.2.4.2
        let acTable = img.huffmanTables[1][acTableID];
        let quantTable = img.quantTables[component.quantTableID];
         # of H,V blocks (data units) per MCU in the component
        let h = component.hSampleFactor;
        let v = component.vSampleFactor;
         Top-left pixel coordinates of the MCU within the component
         mcuY: # vert MCUs * v blocks/MCU * block size * line stride of component
        let mcuY = vMCU * v * DATA_UNIT_SIZE * component.hSize;
         mcuX: mcuY + (# horiz MCUs * h blocks/MCU * block size)
        let mcuX = mcuY + (hMCU * h * DATA_UNIT_SIZE);
        let block;
        for (let y = 0; y < v; y++) {    Iterate over blocks in the MCU
            for (let x = 0; x < h; x++) {    Iterate over blocks in the MCU
                 Block is the decoded image data. Store it in a component
                block = decodeDataUnit(reader, img, scan, id, dcTable, acTable, quantTable);
                 Top-left coordinates of the block within the MCU
                let topX = x * DATA_UNIT_SIZE;
                let topY = y * DATA_UNIT_SIZE * component.hSize;
                 Copy block contents to component
                for (let yy = 0; yy < DATA_UNIT_SIZE; yy++) {    yy is local y coordinate in block
                    let blockLineStart = mcuX + topY + topX + (yy * component.hSize);
                    for (let xx = 0; xx < DATA_UNIT_SIZE; xx++) {    xx is local x coordinate in block
                        let idx = blockLineStart + xx;
                        if (component.imgBuff[idx] != 0) {
                            console.warn("Warning: overwriting imgBuf data: idx=" + idx
                            + ", x=" + x + ", y=" + y + ", h=" + h + ", v=" + v + ", hMCU="
                            + hMCU + ", vMCU=" + vMCU + ", topX=" + topX + ", topY="
                            + topY + ", yy=" + yy + ", xx=" + xx + ", blockLineStart=" + blockLineStart);
                        }
                        component.imgBuff[idx] = block[yy * DATA_UNIT_SIZE + xx];
                    }
                }
            }
        }
    }
}
function decodeMCU ( reader , img , scan , vMCU , hMCU ) { for ( let i = 0 ; i < scan . orderedComponents . length ; i ++ ) { let component = scan . orderedComponents [ i ] ; let id = component . componentID ; let dcTableID = 0 ; let acTableID = 0 ; for ( let j = 0 ; j < scan . components . length ; j ++ ) { let sc = scan . components [ j ] ; if ( sc [ 0 ] === id ) { dcTableID = sc [ 1 ] ; acTableID = sc [ 2 ] ; break ; } } let dcTable = img . huffmanTables [ 0 ] [ dcTableID ] ; let acTable = img . huffmanTables [ 1 ] [ acTableID ] ; let quantTable = img . quantTables [ component . quantTableID ] ; let h = component . hSampleFactor ; let v = component . vSampleFactor ; let mcuY = vMCU * v * DATA_UNIT_SIZE * component . hSize ; let mcuX = mcuY + ( hMCU * h * DATA_UNIT_SIZE ) ; let block ; for ( let y = 0 ; y < v ; y ++ ) { for ( let x = 0 ; x < h ; x ++ ) { block = decodeDataUnit ( reader , img , scan , id , dcTable , acTable , quantTable ) ; let topX = x * DATA_UNIT_SIZE ; let topY = y * DATA_UNIT_SIZE * component . hSize ; for ( let yy = 0 ; yy < DATA_UNIT_SIZE ; yy ++ ) { let blockLineStart = mcuX + topY + topX + ( yy * component . hSize ) ; for ( let xx = 0 ; xx < DATA_UNIT_SIZE ; xx ++ ) { let idx = blockLineStart + xx ; if ( component . imgBuff [ idx ] != 0 ) { console . warn ( "Warning: overwriting imgBuf data: idx=" + idx + ", x=" + x + ", y=" + y + ", h=" + h + ", v=" + v + ", hMCU=" + hMCU + ", vMCU=" + vMCU + ", topX=" + topX + ", topY=" + topY + ", yy=" + yy + ", xx=" + xx + ", blockLineStart=" + blockLineStart ) ; } component . imgBuff [ idx ] = block [ yy * DATA_UNIT_SIZE + xx ] ; } } } } } }
Decode all of the data blocks in the MCU.
Decode all of the data blocks in the MCU .
// TODO: rename scan.components vs scan.orderedComponents, it's confusing. Can we // just merge into a big 'component' data structure that has both the component // info from the frame and the component info from the scan header? Probably // breaks for hierachical images, but so what? // // Also want to bolt on the ZZ tables to Component....time to make a component class? // Find the component metadata in the scan so we can look up huff tables. Ugh so messy // for (sc of scan.components) { // 0 is DC table, 1 is AC table: B.2.4.2 // # of H,V blocks (data units) per MCU in the component // Top-left pixel coordinates of the MCU within the component // mcuY: # vert MCUs * v blocks/MCU * block size * line stride of component // mcuX: mcuY + (# horiz MCUs * h blocks/MCU * block size) // Iterate over blocks in the MCU // Iterate over blocks in the MCU // Block is the decoded image data. Store it in a component // Top-left coordinates of the block within the MCU // Copy block contents to component // yy is local y coordinate in block // xx is local x coordinate in block