📄 jpxstream.cc
字号:
} else if (csEnum == jpxCSCMYK) { csMode1 = streamCSDeviceCMYK; } else if (csEnum == jpxCSsRGB || csEnum == jpxCSCISesRGB || csEnum == jpxCSROMMRGB) { csMode1 = streamCSDeviceRGB; } if (csMode1 != streamCSNone && (!haveCSMode || csPrec1 > csPrec)) { *csMode = csMode1; csPrec = csPrec1; haveCSMode = gTrue; } for (i = 0; i < dataLen - 7; ++i) { str->getChar(); } } } else { for (i = 0; i < dataLen - 3; ++i) { str->getChar(); } } } } else if (boxType == 0x6A703263) { // codestream if (!(haveBPC && haveCSMode)) { getImageParams2(bitsPerComponent, csMode); } break; } else { for (i = 0; i < dataLen; ++i) { str->getChar(); } } } } str->close();}// Get image parameters from the codestream.void JPXStream::getImageParams2(int *bitsPerComponent, StreamColorSpaceMode *csMode) { int segType; Guint segLen, nComps1, bpc1, dummy, i; while (readMarkerHdr(&segType, &segLen)) { if (segType == 0x51) { // SIZ - image and tile size if (readUWord(&dummy) && readULong(&dummy) && readULong(&dummy) && readULong(&dummy) && readULong(&dummy) && readULong(&dummy) && readULong(&dummy) && readULong(&dummy) && readULong(&dummy) && readUWord(&nComps1) && readUByte(&bpc1)) { *bitsPerComponent = (bpc1 & 0x7f) + 1; // if there's no color space info, take a guess if (nComps1 == 1) { *csMode = streamCSDeviceGray; } else if (nComps1 == 3) { *csMode = streamCSDeviceRGB; } else if (nComps1 == 4) { *csMode = streamCSDeviceCMYK; } } break; } else { if (segLen > 2) { for (i = 0; i < segLen - 2; ++i) { str->getChar(); } } } }}GBool JPXStream::readBoxes() { Guint boxType, boxLen, dataLen; Guint bpc1, compression, unknownColorspace, ipr; Guint i, j; haveImgHdr = gFalse; // check for a naked JPEG 2000 codestream (without the JP2/JPX // wrapper) -- this appears to be a violation of the PDF spec, but // Acrobat allows it if (str->lookChar() == 0xff) { error(getPos(), "Naked JPEG 2000 codestream, missing JP2/JPX wrapper"); readCodestream(0); nComps = img.nComps; bpc = (Guint *)gmallocn(nComps, sizeof(Guint)); for (i = 0; i < nComps; ++i) { bpc[i] = img.tiles[0].tileComps[i].prec; } width = img.xSize - img.xOffset; height = img.ySize - img.yOffset; return gTrue; } while (readBoxHdr(&boxType, &boxLen, &dataLen)) { switch (boxType) { case 0x6a703268: // JP2 header // this is a grouping box ('superbox') which has no real // contents and doesn't appear to be used consistently, i.e., // some things which should be subboxes of the JP2 header box // show up outside of it - so we simply ignore the JP2 header // box break; case 0x69686472: // image header if (!readULong(&height) || !readULong(&width) || !readUWord(&nComps) || !readUByte(&bpc1) || !readUByte(&compression) || !readUByte(&unknownColorspace) || !readUByte(&ipr)) { error(getPos(), "Unexpected EOF in JPX stream"); return gFalse; } if (compression != 7) { error(getPos(), "Unknown compression type in JPX stream"); return gFalse; } bpc = (Guint *)gmallocn(nComps, sizeof(Guint)); for (i = 0; i < nComps; ++i) { bpc[i] = bpc1; } haveImgHdr = gTrue; break; case 0x62706363: // bits per component if (!haveImgHdr) { error(getPos(), "Found bits per component box before image header box in JPX stream"); return gFalse; } if (dataLen != nComps) { error(getPos(), "Invalid bits per component box in JPX stream"); return gFalse; } for (i = 0; i < nComps; ++i) { if (!readUByte(&bpc[i])) { error(getPos(), "Unexpected EOF in JPX stream"); return gFalse; } } break; case 0x636F6C72: // color specification if (!readColorSpecBox(dataLen)) { return gFalse; } break; case 0x70636c72: // palette if (!readUWord(&palette.nEntries) || !readUByte(&palette.nComps)) { error(getPos(), "Unexpected EOF in JPX stream"); return gFalse; } palette.bpc = (Guint *)gmallocn(palette.nComps, sizeof(Guint)); palette.c = (int *)gmallocn(palette.nEntries * palette.nComps, sizeof(int)); for (i = 0; i < palette.nComps; ++i) { if (!readUByte(&palette.bpc[i])) { error(getPos(), "Unexpected EOF in JPX stream"); return gFalse; } ++palette.bpc[i]; } for (i = 0; i < palette.nEntries; ++i) { for (j = 0; j < palette.nComps; ++j) { if (!readNBytes(((palette.bpc[j] & 0x7f) + 7) >> 3, (palette.bpc[j] & 0x80) ? gTrue : gFalse, &palette.c[i * palette.nComps + j])) { error(getPos(), "Unexpected EOF in JPX stream"); return gFalse; } } } havePalette = gTrue; break; case 0x636d6170: // component mapping compMap.nChannels = dataLen / 4; compMap.comp = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint)); compMap.type = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint)); compMap.pComp = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint)); for (i = 0; i < compMap.nChannels; ++i) { if (!readUWord(&compMap.comp[i]) || !readUByte(&compMap.type[i]) || !readUByte(&compMap.pComp[i])) { error(getPos(), "Unexpected EOF in JPX stream"); return gFalse; } } haveCompMap = gTrue; break; case 0x63646566: // channel definition if (!readUWord(&channelDefn.nChannels)) { error(getPos(), "Unexpected EOF in JPX stream"); return gFalse; } channelDefn.idx = (Guint *)gmallocn(channelDefn.nChannels, sizeof(Guint)); channelDefn.type = (Guint *)gmallocn(channelDefn.nChannels, sizeof(Guint)); channelDefn.assoc = (Guint *)gmallocn(channelDefn.nChannels, sizeof(Guint)); for (i = 0; i < channelDefn.nChannels; ++i) { if (!readUWord(&channelDefn.idx[i]) || !readUWord(&channelDefn.type[i]) || !readUWord(&channelDefn.assoc[i])) { error(getPos(), "Unexpected EOF in JPX stream"); return gFalse; } } haveChannelDefn = gTrue; break; case 0x6A703263: // contiguous codestream if (!bpc) { error(getPos(), "JPX stream is missing the image header box"); } if (!haveCS) { error(getPos(), "JPX stream has no supported color spec"); } if (!readCodestream(dataLen)) { return gFalse; } break; default: for (i = 0; i < dataLen; ++i) { if (str->getChar() == EOF) { error(getPos(), "Unexpected EOF in JPX stream"); return gFalse; } } break; } } return gTrue;}GBool JPXStream::readColorSpecBox(Guint dataLen) { JPXColorSpec newCS; Guint csApprox, csEnum; Guint i; GBool ok; ok = gFalse; if (!readUByte(&newCS.meth) || !readByte(&newCS.prec) || !readUByte(&csApprox)) { goto err; } switch (newCS.meth) { case 1: // enumerated colorspace if (!readULong(&csEnum)) { goto err; } newCS.enumerated.type = (JPXColorSpaceType)csEnum; switch (newCS.enumerated.type) { case jpxCSBiLevel: ok = gTrue; break; case jpxCSYCbCr1: ok = gTrue; break; case jpxCSYCbCr2: ok = gTrue; break; case jpxCSYCBCr3: ok = gTrue; break; case jpxCSPhotoYCC: ok = gTrue; break; case jpxCSCMY: ok = gTrue; break; case jpxCSCMYK: ok = gTrue; break; case jpxCSYCCK: ok = gTrue; break; case jpxCSCIELab: if (dataLen == 7 + 7*4) { if (!readULong(&newCS.enumerated.cieLab.rl) || !readULong(&newCS.enumerated.cieLab.ol) || !readULong(&newCS.enumerated.cieLab.ra) || !readULong(&newCS.enumerated.cieLab.oa) || !readULong(&newCS.enumerated.cieLab.rb) || !readULong(&newCS.enumerated.cieLab.ob) || !readULong(&newCS.enumerated.cieLab.il)) { goto err; } } else if (dataLen == 7) { //~ this assumes the 8-bit case newCS.enumerated.cieLab.rl = 100; newCS.enumerated.cieLab.ol = 0; newCS.enumerated.cieLab.ra = 255; newCS.enumerated.cieLab.oa = 128; newCS.enumerated.cieLab.rb = 255; newCS.enumerated.cieLab.ob = 96; newCS.enumerated.cieLab.il = 0x00443530; } else { goto err; } ok = gTrue; break; case jpxCSsRGB: ok = gTrue; break; case jpxCSGrayscale: ok = gTrue; break; case jpxCSBiLevel2: ok = gTrue; break; case jpxCSCIEJab: // not allowed in PDF goto err; case jpxCSCISesRGB: ok = gTrue; break; case jpxCSROMMRGB: ok = gTrue; break; case jpxCSsRGBYCbCr: ok = gTrue; break; case jpxCSYPbPr1125: ok = gTrue; break; case jpxCSYPbPr1250: ok = gTrue; break; default: goto err; } break; case 2: // restricted ICC profile case 3: // any ICC profile (JPX) case 4: // vendor color (JPX) for (i = 0; i < dataLen - 3; ++i) { if (str->getChar() == EOF) { goto err; } } break; } if (ok && (!haveCS || newCS.prec > cs.prec)) { cs = newCS; haveCS = gTrue; } return gTrue; err: error(getPos(), "Error in JPX color spec"); return gFalse;}GBool JPXStream::readCodestream(Guint len) { JPXTile *tile; JPXTileComp *tileComp; int segType; GBool haveSIZ, haveCOD, haveQCD, haveSOT; Guint precinctSize, style; Guint segLen, capabilities, comp, i, j, r; //----- main header haveSIZ = haveCOD = haveQCD = haveSOT = gFalse; do { if (!readMarkerHdr(&segType, &segLen)) { error(getPos(), "Error in JPX codestream"); return gFalse; } switch (segType) { case 0x4f: // SOC - start of codestream // marker only break; case 0x51: // SIZ - image and tile size if (!readUWord(&capabilities) || !readULong(&img.xSize) || !readULong(&img.ySize) || !readULong(&img.xOffset) || !readULong(&img.yOffset) || !readULong(&img.xTileSize) || !readULong(&img.yTileSize) || !readULong(&img.xTileOffset) || !readULong(&img.yTileOffset) || !readUWord(&img.nComps)) { error(getPos(), "Error in JPX SIZ marker segment"); return gFalse; } if (haveImgHdr && img.nComps != nComps) { error(getPos(), "Different number of components in JPX SIZ marker segment"); return gFalse; } img.nXTiles = (img.xSize - img.xTileOffset + img.xTileSize - 1) / img.xTileSize; img.nYTiles = (img.ySize - img.yTileOffset + img.yTileSize - 1) / img.yTileSize; // check for overflow before allocating memory if (img.nXTiles <= 0 || img.nYTiles <= 0 || img.nXTiles >= INT_MAX / img.nYTiles) { error(getPos(), "Bad tile count in JPX SIZ marker segment"); return gFalse; } img.tiles = (JPXTile *)gmallocn(img.nXTiles * img.nYTiles, sizeof(JPXTile)); for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { img.tiles[i].tileComps = (JPXTileComp *)gmallocn(img.nComps, sizeof(JPXTileComp)); for (comp = 0; comp < img.nComps; ++comp) { img.tiles[i].tileComps[comp].quantSteps = NULL; img.tiles[i].tileComps[comp].data = NULL; img.tiles[i].tileComps[comp].buf = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -