diff --git a/cmd/bitmaphook.cpp b/cmd/bitmaphook.cpp index 569a262..cd67bc8 100644 --- a/cmd/bitmaphook.cpp +++ b/cmd/bitmaphook.cpp @@ -33,7 +33,6 @@ /// Includes #include "cmd/bitmaphook.hpp" -#include "cmd/iohelpers.hpp" #include "std/stdio.hpp" #include "std/stdlib.hpp" #include "std/string.hpp" @@ -281,10 +280,16 @@ JPG_LONG BitmapHook(struct JPG_Hook *hook, struct JPG_TagItem *tags) switch(bmm->bmm_usDepth) { case 1: case 3: // The direct cases, can write PPM right away. -#ifdef JPG_LIL_ENDIAN + // On those bloddy little endian machines, an endian swap is necessary // as PNM is big-endian. - if (bmm->bmm_ucPixelType == CTYP_UWORD) { + bool turnBytePairs = bmm->bmm_ucPixelType == CTYP_UWORD; +#ifdef JPG_LIL_ENDIAN + turnBytePairs &= bmm->bmm_decodedFormat == PPM; +#else + turnBytePairs &= bmm->bmm_decodedFormat == RAW; +#endif + if (turnBytePairs) { ULONG count = bmm->bmm_ulWidth * height * bmm->bmm_usDepth; UWORD *data = (UWORD *)bmm->bmm_pMemPtr; do { @@ -292,9 +297,10 @@ JPG_LONG BitmapHook(struct JPG_Hook *hook, struct JPG_TagItem *tags) data++; } while(--count); } -#endif - fwrite(bmm->bmm_pMemPtr,bmm->bmm_ucPixelType & CTYP_SIZE_MASK, - bmm->bmm_ulWidth * height * bmm->bmm_usDepth,bmm->bmm_pTarget); + + const size_t dataSize = + (bmm->bmm_ucPixelType & CTYP_SIZE_MASK) * bmm->bmm_ulWidth * height * bmm->bmm_usDepth; + bmm->bmm_pTarget->write(bmm->bmm_pMemPtr, dataSize); break; } } @@ -455,8 +461,10 @@ JPG_LONG AlphaHook(struct JPG_Hook *hook, struct JPG_TagItem *tags) } while(--count); } #endif - fwrite(bmm->bmm_pAlphaPtr,bmm->bmm_ucAlphaType & CTYP_SIZE_MASK, - bmm->bmm_ulWidth * height,bmm->bmm_pAlphaTarget); + const size_t dataSize = (bmm->bmm_ucAlphaType & CTYP_SIZE_MASK) * bmm->bmm_ulWidth * height; + bmm->bmm_pAlphaTarget->write(bmm->bmm_pMemPtr, dataSize); + //fwrite(bmm->bmm_pAlphaPtr,bmm->bmm_ucAlphaType & CTYP_SIZE_MASK, + // bmm->bmm_ulWidth * height,bmm->bmm_pAlphaTarget); } } } diff --git a/cmd/bitmaphook.hpp b/cmd/bitmaphook.hpp index 0d957bd..d3a862b 100644 --- a/cmd/bitmaphook.hpp +++ b/cmd/bitmaphook.hpp @@ -37,6 +37,7 @@ /// Includes #include "interface/types.hpp" #include "std/stdio.hpp" +#include "cmd/iohelpers.hpp" /// /// Forwards @@ -54,10 +55,10 @@ struct BitmapMemory { UWORD bmm_usDepth; // number of components. UBYTE bmm_ucPixelType; // precision etc. UBYTE bmm_ucAlphaType; // pixel type of the alpha channel - FILE *bmm_pTarget; // where to write the data to. + HookDataAccessor *bmm_pTarget; // where to write the data to. FILE *bmm_pSource; // where the data comes from on reading (encoding) FILE *bmm_pLDRSource; // if there is a separate source for the LDR image, this is non-NULL. - FILE *bmm_pAlphaTarget;// where the alpha (if any) goes to on decoding + HookDataAccessor *bmm_pAlphaTarget;// where the alpha (if any) goes to on decoding FILE *bmm_pAlphaSource;// where the alpha data (if any) comes from. There is no dedicated alpha LDR file const UWORD *bmm_HDR2LDR; // the (simple global) tone mapper used for encoding the image. bool bmm_bFloat; // is true if the input is floating point @@ -68,6 +69,7 @@ struct BitmapMemory { bool bmm_bNoAlphaOutputConversion; // ditto for alpha bool bmm_bClamp; // if set, clamp negative values to zero. bool bmm_bAlphaClamp; // if set, alpha values outside [0,1] will be clamped to range + DecodedFormat bmm_decodedFormat; // decoded format(ppm or raw) }; /// diff --git a/cmd/encodec.cpp b/cmd/encodec.cpp index 5f982ce..2bd24e6 100644 --- a/cmd/encodec.cpp +++ b/cmd/encodec.cpp @@ -326,6 +326,7 @@ void EncodeC(const char *source,const char *ldrsource,const char *target,const c } // FILE *out = fopen(target,"wb"); + FileHookDataAccessor outFileDataAccessor(out); if (out) { int frametype = JPGFLAG_SEQUENTIAL; int residualtype = JPGFLAG_RESIDUAL; @@ -643,7 +644,7 @@ void EncodeC(const char *source,const char *ldrsource,const char *target,const c ok = jpeg->ProvideImage(tags); if (ok) { - struct JPG_Hook filehook(FileHook,out); + struct JPG_Hook filehook(FileHook, &outFileDataAccessor); struct JPG_TagItem iotags[] = { JPG_PointerTag(JPGTAG_HOOK_IOHOOK,&filehook), JPG_PointerTag(JPGTAG_HOOK_IOSTREAM,out), diff --git a/cmd/filehook.cpp b/cmd/filehook.cpp index 4ae468d..1abca8d 100644 --- a/cmd/filehook.cpp +++ b/cmd/filehook.cpp @@ -37,28 +37,90 @@ #include "interface/hooks.hpp" #include "interface/tagitem.hpp" #include "interface/parameters.hpp" -#include "std/stdio.hpp" +#include "std/assert.hpp" +#include /// +HookDataAccessor::~HookDataAccessor() +{ +} + +FileHookDataAccessor::FileHookDataAccessor(FILE *file): m_file(file) +{ +} + +JPG_LONG FileHookDataAccessor::write(JPG_CPTR data, JPG_LONG size) +{ + return fwrite(data, 1, size, m_file); +} + +JPG_LONG FileHookDataAccessor::read(JPG_APTR destination, JPG_LONG size) +{ + return fread(destination, 1, size, m_file); +} + +JPG_LONG FileHookDataAccessor::seek(JPG_LONG offset, JPG_LONG origin) +{ + return fseek(m_file, offset, origin); +} + +UserDataHookAccessor::UserDataHookAccessor(JPG_APTR data, JPG_LONG dataSize): + m_data(reinterpret_cast(data)), m_dataSize(dataSize), m_curPosition(0) +{ +} + +JPG_LONG UserDataHookAccessor::read(JPG_APTR destination, JPG_LONG size) +{ + const JPG_LONG bytesNumberToCopy = std::min(size, m_dataSize - m_curPosition); + memcpy(destination, m_data + m_curPosition, bytesNumberToCopy); + m_curPosition += bytesNumberToCopy; + return bytesNumberToCopy; +} + +JPG_LONG UserDataHookAccessor::write(JPG_CPTR data, JPG_LONG size) +{ + const JPG_LONG bytesNumberToCopy = std::min(size, m_dataSize - m_curPosition); + memcpy(m_data + m_curPosition, data, bytesNumberToCopy); + m_curPosition += bytesNumberToCopy; + return bytesNumberToCopy; +} + +JPG_LONG UserDataHookAccessor::seek(JPG_LONG offset, JPG_LONG origin) +{ + switch(origin) { + case SEEK_CUR: + m_curPosition += offset; + break; + case SEEK_SET: + m_curPosition = offset; + break; + case SEEK_END: + m_curPosition = m_dataSize - offset; + break; + } + + return 0; +} + /// The IO hook function JPG_LONG FileHook(struct JPG_Hook *hook, struct JPG_TagItem *tags) { - FILE *in = (FILE *)(hook->hk_pData); + HookDataAccessor *in = (HookDataAccessor *)(hook->hk_pData); switch(tags->GetTagData(JPGTAG_FIO_ACTION)) { case JPGFLAG_ACTION_READ: { UBYTE *buffer = (UBYTE *)tags->GetTagPtr(JPGTAG_FIO_BUFFER); ULONG size = (ULONG )tags->GetTagData(JPGTAG_FIO_SIZE); - - return fread(buffer,1,size,in); + + return in->read(buffer, size); } case JPGFLAG_ACTION_WRITE: { UBYTE *buffer = (UBYTE *)tags->GetTagPtr(JPGTAG_FIO_BUFFER); ULONG size = (ULONG )tags->GetTagData(JPGTAG_FIO_SIZE); - - return fwrite(buffer,1,size,in); + + return in->write(buffer, size); } case JPGFLAG_ACTION_SEEK: { @@ -67,11 +129,11 @@ JPG_LONG FileHook(struct JPG_Hook *hook, struct JPG_TagItem *tags) switch(mode) { case JPGFLAG_OFFSET_CURRENT: - return fseek(in,offset,SEEK_CUR); + return in->seek(offset, SEEK_CUR); case JPGFLAG_OFFSET_BEGINNING: - return fseek(in,offset,SEEK_SET); + return in->seek(offset, SEEK_SET); case JPGFLAG_OFFSET_END: - return fseek(in,offset,SEEK_END); + return in->seek(offset, SEEK_END); } } case JPGFLAG_ACTION_QUERY: diff --git a/cmd/filehook.hpp b/cmd/filehook.hpp index 564e1d7..6a1c4a3 100644 --- a/cmd/filehook.hpp +++ b/cmd/filehook.hpp @@ -36,6 +36,8 @@ /// Includes #include "interface/types.hpp" +#include "std/stdio.hpp" +#include /// /// Forwards @@ -43,6 +45,40 @@ struct JPG_Hook; struct JPG_TagItem; /// +struct HookDataAccessor +{ + virtual JPG_LONG read(JPG_APTR destination, JPG_LONG size) = 0; + virtual JPG_LONG write(JPG_CPTR data, JPG_LONG size) = 0; + virtual JPG_LONG seek(JPG_LONG offset, JPG_LONG origin) = 0; + virtual ~HookDataAccessor(); +}; + +struct FileHookDataAccessor: public HookDataAccessor +{ + FileHookDataAccessor(FILE *file); + + virtual JPG_LONG read(JPG_APTR destination, JPG_LONG size); + virtual JPG_LONG write(JPG_CPTR data, JPG_LONG size); + virtual JPG_LONG seek(JPG_LONG offset, JPG_LONG origin); + +private: + FILE *m_file; +}; + +struct UserDataHookAccessor: public HookDataAccessor +{ + UserDataHookAccessor(JPG_APTR data, JPG_LONG dataSize); + + virtual JPG_LONG read(JPG_APTR destination, JPG_LONG size); + virtual JPG_LONG write(JPG_CPTR data, JPG_LONG size); + virtual JPG_LONG seek(JPG_LONG offset, JPG_LONG origin); + +private: + UBYTE* m_data; + JPG_LONG m_dataSize; + JPG_LONG m_curPosition; +}; + /// Prototypes extern JPG_LONG FileHook(struct JPG_Hook *hook, struct JPG_TagItem *tags); /// diff --git a/cmd/iohelpers.hpp b/cmd/iohelpers.hpp index e816270..adc0726 100644 --- a/cmd/iohelpers.hpp +++ b/cmd/iohelpers.hpp @@ -37,6 +37,7 @@ #include "interface/types.hpp" #include "std/stdio.hpp" #include "std/math.hpp" +#include "cmd/filehook.hpp" /// /// Prototypes @@ -133,7 +134,7 @@ double inline readFloat(FILE *in,bool bigendian) /// writeFloat // Write a floating point number to a file -void inline writeFloat(FILE *out,FLOAT f,bool bigendian) +void inline writeFloat(HookDataAccessor *out,FLOAT f,bool bigendian) { union { LONG long_buf; @@ -141,18 +142,19 @@ void inline writeFloat(FILE *out,FLOAT f,bool bigendian) } u; u.float_buf = f; + UBYTE* data = reinterpret_cast(&u.long_buf); if (bigendian) { - putc(u.long_buf >> 24,out); - putc(u.long_buf >> 16,out); - putc(u.long_buf >> 8,out); - putc(u.long_buf >> 0,out); - } else { - putc(u.long_buf >> 0,out); - putc(u.long_buf >> 8,out); - putc(u.long_buf >> 16,out); - putc(u.long_buf >> 24,out); + UBYTE byteForSwap = data[0]; + data[0] = data[3]; + data[3] = byteForSwap; + + byteForSwap = data[1]; + data[1] = data[2]; + data[2] = byteForSwap; } + + out->write(data, 4); } /// diff --git a/cmd/main.cpp b/cmd/main.cpp index e5e7176..355233e 100644 --- a/cmd/main.cpp +++ b/cmd/main.cpp @@ -199,6 +199,7 @@ void PrintUsage(const char *progname) "-N : enable noise shaping of the prediction residual\n" "-l : enable lossless coding without a residual image by an\n" " int-to-int DCT, also requires -c and -q 100 for true lossless\n" + "-raw : decoding to raw(not ppm)\n" #if ACCUSOFT_CODE "-p : JPEG lossless (predictive) mode\n" " also requires -c for true lossless\n" @@ -379,6 +380,7 @@ int main(int argc,char **argv) bool noclamp = false; bool setprofile = false; bool median = true; + bool raw = false; int splitquality = -1; int profile = 2; // profile C. const char *sub = NULL; @@ -430,6 +432,10 @@ int main(int argc,char **argv) median = true; argv++; argc--; + } else if (!strcmp(argv[1],"-raw")) { + raw = true; + argv++; + argc--; } else if (!strcmp(argv[1],"-ct")) { median = false; argv++; @@ -691,7 +697,7 @@ int main(int argc,char **argv) } if (quality < 0 && lossless == false && lsmode < 0) { - Reconstruct(argv[1],argv[2],colortrafo,alpha); + Reconstruct(argv[1], argv[2], (raw ? RAW : PPM), colortrafo, alpha); } else { switch(profile) { case 0: diff --git a/cmd/reconstruct.cpp b/cmd/reconstruct.cpp index f88f828..47261b4 100644 --- a/cmd/reconstruct.cpp +++ b/cmd/reconstruct.cpp @@ -39,183 +39,228 @@ #include "cmd/filehook.hpp" #include "tools/environment.hpp" #include "tools/traits.hpp" -#include "interface/types.hpp" #include "interface/hooks.hpp" #include "interface/tagitem.hpp" -#include "interface/parameters.hpp" #include "interface/jpeg.hpp" /// -/// Reconstruct -// This reconstructs an image from the given input file -// and writes the output ppm. -void Reconstruct(const char *infile,const char *outfile, - int colortrafo,const char *alpha) -{ - FILE *in = fopen(infile,"rb"); - if (in) { - struct JPG_Hook filehook(FileHook,in); - class JPEG *jpeg = JPEG::Construct(NULL); - if (jpeg) { - int ok = 1; - struct JPG_TagItem tags[] = { - JPG_PointerTag(JPGTAG_HOOK_IOHOOK,&filehook), - JPG_PointerTag(JPGTAG_HOOK_IOSTREAM,in), - JPG_ValueTag(JPGTAG_MATRIX_LTRAFO,colortrafo), - JPG_EndTag - }; - - if (jpeg->Read(tags)) { - struct JPG_TagItem atags[] = { - JPG_ValueTag(JPGTAG_IMAGE_PRECISION,0), - JPG_ValueTag(JPGTAG_IMAGE_IS_FLOAT,false), - JPG_ValueTag(JPGTAG_IMAGE_OUTPUT_CONVERSION,true), - JPG_EndTag - }; - struct JPG_TagItem itags[] = { - JPG_ValueTag(JPGTAG_IMAGE_WIDTH,0), - JPG_ValueTag(JPGTAG_IMAGE_HEIGHT,0), - JPG_ValueTag(JPGTAG_IMAGE_DEPTH,0), - JPG_ValueTag(JPGTAG_IMAGE_PRECISION,0), - JPG_ValueTag(JPGTAG_IMAGE_IS_FLOAT,false), - JPG_ValueTag(JPGTAG_IMAGE_OUTPUT_CONVERSION,true), - JPG_ValueTag(JPGTAG_ALPHA_MODE,JPGFLAG_ALPHA_OPAQUE), - JPG_PointerTag(JPGTAG_ALPHA_TAGLIST,atags), +void reconstruct(HookDataAccessor* input, HookDataAccessor* output, HookDataAccessor* alpha, + DecodedFormat outFormat, int colortrafo) +{ + if(!input || ! output) + return; + + struct JPG_Hook filehook(FileHook, input); + class JPEG *jpeg = JPEG::Construct(NULL); + + if(!jpeg) + { + fprintf(stderr,"failed to construct the JPEG object"); + return; + } + + int ok = 1; + struct JPG_TagItem tags[] = { + JPG_PointerTag(JPGTAG_HOOK_IOHOOK,&filehook), + JPG_PointerTag(JPGTAG_HOOK_IOSTREAM,input), + JPG_ValueTag(JPGTAG_MATRIX_LTRAFO,colortrafo), + JPG_EndTag + }; + + if (jpeg->Read(tags)) { + struct JPG_TagItem atags[] = { + JPG_ValueTag(JPGTAG_IMAGE_PRECISION,0), + JPG_ValueTag(JPGTAG_IMAGE_IS_FLOAT,false), + JPG_ValueTag(JPGTAG_IMAGE_OUTPUT_CONVERSION,true), + JPG_EndTag + }; + struct JPG_TagItem itags[] = { + JPG_ValueTag(JPGTAG_IMAGE_WIDTH,0), + JPG_ValueTag(JPGTAG_IMAGE_HEIGHT,0), + JPG_ValueTag(JPGTAG_IMAGE_DEPTH,0), + JPG_ValueTag(JPGTAG_IMAGE_PRECISION,0), + JPG_ValueTag(JPGTAG_IMAGE_IS_FLOAT,false), + JPG_ValueTag(JPGTAG_IMAGE_OUTPUT_CONVERSION,true), + JPG_ValueTag(JPGTAG_ALPHA_MODE,JPGFLAG_ALPHA_OPAQUE), + JPG_PointerTag(JPGTAG_ALPHA_TAGLIST,atags), + JPG_EndTag + }; + if (jpeg->GetInformation(itags)) { + ULONG width = itags->GetTagData(JPGTAG_IMAGE_WIDTH); + ULONG height = itags->GetTagData(JPGTAG_IMAGE_HEIGHT); + UBYTE depth = itags->GetTagData(JPGTAG_IMAGE_DEPTH); + UBYTE prec = itags->GetTagData(JPGTAG_IMAGE_PRECISION); + UBYTE aprec = 0; + bool pfm = itags->GetTagData(JPGTAG_IMAGE_IS_FLOAT)?true:false; + bool convert = itags->GetTagData(JPGTAG_IMAGE_OUTPUT_CONVERSION)?true:false; + bool doalpha = itags->GetTagData(JPGTAG_ALPHA_MODE,JPGFLAG_ALPHA_OPAQUE)?true:false; + bool apfm = false; + bool aconvert= false; + + if (alpha && doalpha) { + aprec = atags->GetTagData(JPGTAG_IMAGE_PRECISION); + apfm = atags->GetTagData(JPGTAG_IMAGE_IS_FLOAT)?true:false; + aconvert = atags->GetTagData(JPGTAG_IMAGE_OUTPUT_CONVERSION)?true:false; + } else { + doalpha = false; // alpha channel is ignored. + } + + UBYTE bytesperpixel = sizeof(UBYTE); + UBYTE pixeltype = CTYP_UBYTE; + if (prec > 8) { + bytesperpixel = sizeof(UWORD); + pixeltype = CTYP_UWORD; + } + if (pfm && convert == false) { + bytesperpixel = sizeof(FLOAT); + pixeltype = CTYP_FLOAT; + } + + UBYTE alphabytesperpixel = sizeof(UBYTE); + UBYTE alphapixeltype = CTYP_UBYTE; + if (aprec > 8) { + alphabytesperpixel = sizeof(UWORD); + alphapixeltype = CTYP_UWORD; + } + if (apfm && aconvert == false) { + alphabytesperpixel = sizeof(FLOAT); + alphapixeltype = CTYP_FLOAT; + } + + UBYTE *amem = NULL; + UBYTE *mem = (UBYTE *)malloc(width * 8 * depth * bytesperpixel); + if (doalpha) + amem = (UBYTE *)malloc(width * 8 * alphabytesperpixel); // only one component! + + if (mem) { + struct BitmapMemory bmm; + bmm.bmm_pMemPtr = mem; + bmm.bmm_pAlphaPtr = amem; + bmm.bmm_ulWidth = width; + bmm.bmm_ulHeight = height; + bmm.bmm_usDepth = depth; + bmm.bmm_ucPixelType = pixeltype; + bmm.bmm_ucAlphaType = alphapixeltype; + bmm.bmm_pTarget = output; + bmm.bmm_pAlphaTarget = doalpha ? alpha : NULL; + bmm.bmm_pSource = NULL; + bmm.bmm_pAlphaSource = NULL; + bmm.bmm_pLDRSource = NULL; + bmm.bmm_bFloat = pfm; + bmm.bmm_bAlphaFloat = apfm; + bmm.bmm_bBigEndian = true; + bmm.bmm_bAlphaBigEndian = true; + bmm.bmm_bNoOutputConversion = !convert; + bmm.bmm_bNoAlphaOutputConversion = !aconvert; + bmm.bmm_decodedFormat = outFormat; + + ULONG y = 0; // Just as a demo, run a stripe-based reconstruction. + ULONG lastline; + struct JPG_Hook bmhook(BitmapHook,&bmm); + struct JPG_Hook alphahook(AlphaHook,&bmm); + struct JPG_TagItem tags[] = { + JPG_PointerTag(JPGTAG_BIH_HOOK,&bmhook), + JPG_PointerTag(JPGTAG_BIH_ALPHAHOOK,&alphahook), + JPG_ValueTag(JPGTAG_DECODER_MINY,y), + JPG_ValueTag(JPGTAG_DECODER_MAXY,y+7), JPG_EndTag }; - if (jpeg->GetInformation(itags)) { - ULONG width = itags->GetTagData(JPGTAG_IMAGE_WIDTH); - ULONG height = itags->GetTagData(JPGTAG_IMAGE_HEIGHT); - UBYTE depth = itags->GetTagData(JPGTAG_IMAGE_DEPTH); - UBYTE prec = itags->GetTagData(JPGTAG_IMAGE_PRECISION); - UBYTE aprec = 0; - bool pfm = itags->GetTagData(JPGTAG_IMAGE_IS_FLOAT)?true:false; - bool convert = itags->GetTagData(JPGTAG_IMAGE_OUTPUT_CONVERSION)?true:false; - bool doalpha = itags->GetTagData(JPGTAG_ALPHA_MODE,JPGFLAG_ALPHA_OPAQUE)?true:false; - bool apfm = false; - bool aconvert= false; - - if (alpha && doalpha) { - aprec = atags->GetTagData(JPGTAG_IMAGE_PRECISION); - apfm = atags->GetTagData(JPGTAG_IMAGE_IS_FLOAT)?true:false; - aconvert = atags->GetTagData(JPGTAG_IMAGE_OUTPUT_CONVERSION)?true:false; - } else { - doalpha = false; // alpha channel is ignored. - } - - UBYTE bytesperpixel = sizeof(UBYTE); - UBYTE pixeltype = CTYP_UBYTE; - if (prec > 8) { - bytesperpixel = sizeof(UWORD); - pixeltype = CTYP_UWORD; - } - if (pfm && convert == false) { - bytesperpixel = sizeof(FLOAT); - pixeltype = CTYP_FLOAT; - } - UBYTE alphabytesperpixel = sizeof(UBYTE); - UBYTE alphapixeltype = CTYP_UBYTE; - if (aprec > 8) { - alphabytesperpixel = sizeof(UWORD); - alphapixeltype = CTYP_UWORD; - } - if (apfm && aconvert == false) { - alphabytesperpixel = sizeof(FLOAT); - alphapixeltype = CTYP_FLOAT; - } + if (outFormat == PPM) + { + char ppmHeaderData[50]; + const JPG_LONG written = sprintf(ppmHeaderData,"P%c\n%d %d\n%d\n", + (pfm)?((depth > 1)?'F':'f'):((depth > 1)?('6'):('5')), + width,height,(pfm)?(1):((1 << prec) - 1)); + output->write(ppmHeaderData, written); - UBYTE *amem = NULL; - UBYTE *mem = (UBYTE *)malloc(width * 8 * depth * bytesperpixel); - if (doalpha) - amem = (UBYTE *)malloc(width * 8 * alphabytesperpixel); // only one component! - - if (mem) { - struct BitmapMemory bmm; - bmm.bmm_pMemPtr = mem; - bmm.bmm_pAlphaPtr = amem; - bmm.bmm_ulWidth = width; - bmm.bmm_ulHeight = height; - bmm.bmm_usDepth = depth; - bmm.bmm_ucPixelType = pixeltype; - bmm.bmm_ucAlphaType = alphapixeltype; - bmm.bmm_pTarget = fopen(outfile,"wb"); - bmm.bmm_pAlphaTarget = (doalpha)?(fopen(alpha,"wb")):NULL; - bmm.bmm_pSource = NULL; - bmm.bmm_pAlphaSource = NULL; - bmm.bmm_pLDRSource = NULL; - bmm.bmm_bFloat = pfm; - bmm.bmm_bAlphaFloat = apfm; - bmm.bmm_bBigEndian = true; - bmm.bmm_bAlphaBigEndian = true; - bmm.bmm_bNoOutputConversion = !convert; - bmm.bmm_bNoAlphaOutputConversion = !aconvert; - - if (bmm.bmm_pTarget) { - ULONG y = 0; // Just as a demo, run a stripe-based reconstruction. - ULONG lastline; - struct JPG_Hook bmhook(BitmapHook,&bmm); - struct JPG_Hook alphahook(AlphaHook,&bmm); - struct JPG_TagItem tags[] = { - JPG_PointerTag(JPGTAG_BIH_HOOK,&bmhook), - JPG_PointerTag(JPGTAG_BIH_ALPHAHOOK,&alphahook), - JPG_ValueTag(JPGTAG_DECODER_MINY,y), - JPG_ValueTag(JPGTAG_DECODER_MAXY,y+7), - JPG_EndTag - }; - fprintf(bmm.bmm_pTarget,"P%c\n%d %d\n%d\n", - (pfm)?((depth > 1)?'F':'f'):((depth > 1)?('6'):('5')), - width,height,(pfm)?(1):((1 << prec) - 1)); - - if (bmm.bmm_pAlphaTarget) - fprintf(bmm.bmm_pAlphaTarget,"P%c\n%d %d\n%d\n", - (apfm)?('f'):('5'), - width,height,(apfm)?(1):((1 << aprec) - 1)); - - // - // Reconstruct now the buffered image, line by line. Could also - // reconstruct the image as a whole. What we have here is just a demo - // that is not necessarily the most efficient way of handling images. - do { - lastline = height; - if (lastline > y + 8) - lastline = y + 8; - tags[2].ti_Data.ti_lData = y; - tags[3].ti_Data.ti_lData = lastline - 1; - ok = jpeg->DisplayRectangle(tags); - y = lastline; - } while(y < height && ok); - - fclose(bmm.bmm_pTarget); - } else { - perror("failed to open the output file"); - } - - if (bmm.bmm_pAlphaTarget) - fclose(bmm.bmm_pAlphaTarget); - - if (amem) - free(amem); - - free(mem); - } else { - fprintf(stderr,"unable to allocate memory to buffer the image"); + if (bmm.bmm_pAlphaTarget) + { + const JPG_LONG written = sprintf(ppmHeaderData,"P%c\n%d %d\n%d\n", + (apfm)?('f'):('5'), + width,height,(apfm)?(1):((1 << aprec) - 1)); + alpha->write(ppmHeaderData, written); } - } else ok = 0; - } else ok = 0; + } + + // + // Reconstruct now the buffered image, line by line. Could also + // reconstruct the image as a whole. What we have here is just a demo + // that is not necessarily the most efficient way of handling images. + do { + lastline = height; + if (lastline > y + 8) + lastline = y + 8; + tags[2].ti_Data.ti_lData = y; + tags[3].ti_Data.ti_lData = lastline - 1; + ok = jpeg->DisplayRectangle(tags); + y = lastline; + } while(y < height && ok); - if (!ok) { - const char *error; - int code = jpeg->LastError(error); - fprintf(stderr,"reading a JPEG file failed - error %d - %s\n",code,error); + if (amem) + free(amem); + + free(mem); + } else { + fprintf(stderr,"unable to allocate memory to buffer the image"); } - JPEG::Destruct(jpeg); - } else { - fprintf(stderr,"failed to construct the JPEG object"); - } - fclose(in); - } else { + } else ok = 0; + } else ok = 0; + + if (!ok) { + const char *error; + int code = jpeg->LastError(error); + fprintf(stderr,"reading a JPEG file failed - error %d - %s\n",code,error); + } + JPEG::Destruct(jpeg); +} + +/// Reconstruct +// This reconstructs an image from the given input file +// and writes the output ppm. +void Reconstruct(const char *infile, const char *outfile, DecodedFormat outFormat, + int colortrafo, const char *alpha) +{ + FILE *in = fopen(infile,"rb"); + FILE *out = fopen(outfile,"wb"); + + if (!in) + { perror("failed to open the input file"); + return; + } + + if (!out) + { + perror("failed to open the output file"); + return; } + + FileHookDataAccessor inDataAccessor(in); + FileHookDataAccessor targetWriter(out); + + FILE *alphaOut = alpha ? fopen(outfile,"wb") : NULL; + FileHookDataAccessor alphaWriter(alphaOut); + + reconstruct(&inDataAccessor, &targetWriter, (alpha ? &alphaWriter : NULL), outFormat, colortrafo); + + fclose(in); + fclose(out); + + if (alphaOut) + fclose(alphaOut); +} + +void ReconstructFromUserData(JPG_APTR input, LONG inputSize, JPG_APTR output, LONG outputSize, + DecodedFormat outFormat, int colortrafo, JPG_APTR alpha, LONG alphaSize) +{ + if (!input || !output) + return; + + UserDataHookAccessor inputDataAccessor(input, inputSize); + UserDataHookAccessor outputWriter(output, outputSize); + UserDataHookAccessor alphaWriter(alpha, alphaSize); + + reconstruct(&inputDataAccessor, &outputWriter, (alpha ? &alphaWriter : NULL), outFormat, colortrafo); } /// diff --git a/cmd/reconstruct.hpp b/cmd/reconstruct.hpp index 8907284..b811a29 100644 --- a/cmd/reconstruct.hpp +++ b/cmd/reconstruct.hpp @@ -35,8 +35,17 @@ #ifndef CMD_RECONSTRUCT_HPP #define CMD_RECONSTRUCT_HPP +#include "interface/types.hpp" +#include "interface/parameters.hpp" + /// Prototypes -extern void Reconstruct(const char *infile,const char *outfile,int colortrafo,const char *alpha); +extern void Reconstruct(const char *infile, const char *outfile, DecodedFormat outFormat = PPM, + int colortrafo = JPGFLAG_MATRIX_COLORTRANSFORMATION_NONE, const char *alpha = NULL); + +extern void ReconstructFromUserData(JPG_APTR input, LONG inputSize, JPG_APTR output, LONG outputSize, + DecodedFormat outFormat = RAW, + int colortrafo = JPGFLAG_MATRIX_COLORTRANSFORMATION_NONE, + JPG_APTR alpha = NULL, LONG alphaSize = 0); /// /// diff --git a/interface/types.hpp b/interface/types.hpp index 9ab60bd..5fa64c7 100644 --- a/interface/types.hpp +++ b/interface/types.hpp @@ -239,5 +239,11 @@ typedef DOUBLE DOUBLE_ALIASED; #endif /// +enum DecodedFormat +{ + PPM, + RAW +}; + /// #endif