home *** CD-ROM | disk | FTP | other *** search
- #include <clib/alib_protos.h>
- #include <pragma/datatypes_lib.h>
- #include <pragma/dos_lib.h>
- #include <pragma/exec_lib.h>
- #include <pragma/graphics_lib.h>
- #include <pragma/intuition_lib.h>
- #include <pragma/jpeg_lib.h>
- #include <pragma/render_lib.h>
- #include <pragma/utility_lib.h>
- #include <render/renderhooks.h>
- #include <cybergraphx/cybergraphics.h>
- #include <datatypes/pictureclass.h>
- #include <exec/memory.h>
- #include <intuition/icclass.h>
- #include <string.h>
- #include "class.h"
-
- struct Arg1
- {
- long *mode,*dither,*depth,*dct,*scale,*quality,*smooth,gray,prog;
- };
-
- ULONG SaveJPEG(IClass *cl,Object *obj,dtWrite *msg);
-
- extern Library *SuperClassBase;
-
- void ReadPrefs(Data *data)
- {
- char *var;
- data->mode=1;
- data->dither=0;
- data->depth=8;
- data->dct=0;
- data->scale=1;
- data->quality=75;
- data->smooth=0;
- data->gray=0;
- data->prog=0;
- if(var=(char *)AllocVec(512,0))
- {
- if(GetVar("ENV:DataTypes/jpeg.prefs",var,512,LV_VAR|GVF_GLOBAL_ONLY)>=0)
- {
- RDArgs *rdargs;
- if(rdargs=(RDArgs *)AllocDosObject(DOS_RDARGS,0))
- {
- RDArgs *args;
- Arg1 para;
- rdargs->RDA_Source.CS_Buffer=var;
- rdargs->RDA_Source.CS_Length=strlen(var);
- rdargs->RDA_Source.CS_CurChr=0;
- memset(¶,0,sizeof(Arg1));
- if(args=ReadArgs("MODE/A/N,DITHER/A/N,DEPTH/A/N,DCT/A/N,SCALE/A/N,QUALITY/A/N,SMOOTH/A/N,GRAY/S,PROGRESSIVE/S",(long *)¶,rdargs))
- {
- data->mode=*para.mode;
- if(data->mode<0) data->mode=0;
- else if(data->mode>1) data->mode=1;
- data->dither=*para.dither;
- if(data->dither<0) data->dither=0;
- else if(data->dither>1) data->dither=1;
- data->depth=*para.depth;
- if(data->depth<3) data->depth=3;
- else if(data->depth>8) data->depth=8;
- data->dct=*para.dct;
- if(data->dct<0) data->dct=0;
- else if(data->dct>2) data->dct=2;
- data->scale=*para.scale;
- if(data->scale<0) data->scale=0;
- else if(data->scale>3) data->scale=3;
- data->scale=1<<data->scale;
- data->quality=*para.quality;
- if(data->quality<1) data->quality=1;
- else if(data->quality>100) data->quality=100;
- data->smooth=*para.smooth;
- if(data->smooth<0) data->smooth=0;
- else if(data->smooth>100) data->smooth=100;
- data->gray=para.gray;
- data->prog=para.prog;
- FreeArgs(args);
- }
- FreeDosObject(DOS_RDARGS,rdargs);
- }
- }
- FreeVec(var);
- }
- if(SuperClassBase->lib_Version<43) data->mode=0;
- }
-
- struct JPEGINFO
- {
- Object *obj;
- RastPort *rp,*trp;
- UBYTE *buffer;
- UWORD d,gray;
- };
-
- static void _getline(UBYTE *scanline,ULONG y,ULONG numb,JPEGINFO *info)
- {
- if(info->gray) WritePixelLine8(info->rp,0,y,numb,scanline,info->trp);
- else
- {
- ULONG w=numb/3;
- if(info->d>8) DoMethod(info->obj,PDTM_WRITEPIXELARRAY,scanline,RECTFMT_RGB,numb,0,y,w,1);
- else
- {
- register ULONG i;
- register UBYTE *p1,*p2;
- p1=info->buffer+w*y*4;
- p2=scanline;
- for(i=0;i<w;i++,p1+=4,p2+=3)
- {
- p1[1]=p2[0];
- p1[2]=p2[1];
- p1[3]=p2[2];
- }
- }
- }
- }
-
- static ULONG getline(register __a0 UBYTE *scanline,register __d0 ULONG line,register __d1 ULONG numb,register __a1 void *userdata)
- {
- _getline(scanline,line-1,numb,(JPEGINFO *)userdata);
- return 0;
- }
-
- ULONG Colors2DT(Object *obj,UBYTE *color)
- {
- UBYTE *cr;
- ULONG *cregs,i,num,error=0;
- GetDTAttrs(obj,PDTA_NumColors,&num,PDTA_ColorRegisters,&cr,PDTA_CRegs,&cregs,TAG_END);
- if(cr&&cregs)
- {
- if(color)
- {
- for(i=0;i<num;i++,cr+=3,cregs+=3,color+=4)
- {
- cr[0]=color[1];
- cr[1]=color[2];
- cr[2]=color[3];
- cregs[0]=cr[0]<<24;
- cregs[1]=cr[1]<<24;
- cregs[2]=cr[2]<<24;
- }
- }
- else
- {
- for(i=0;i<num;i++,cr+=3,cregs+=3)
- {
- cr[0]=i;
- cr[1]=i;
- cr[2]=i;
- cregs[0]=i<<24;
- cregs[1]=cregs[0];
- cregs[2]=cregs[0];
- }
- }
- }
- else error=ERROR_NO_FREE_STORE;
- return error;
- }
-
- static void FillBMHD(Object *obj,BitMapHeader *bh,ULONG w,ULONG h,ULONG depth)
- {
- bh->bmh_Left=0;
- bh->bmh_Top=0;
- bh->bmh_Width=w;
- bh->bmh_Height=h;
- bh->bmh_PageWidth=w;
- bh->bmh_PageHeight=h;
- bh->bmh_Depth=depth;
- bh->bmh_Compression=cmpByteRun1;
- bh->bmh_XAspect=0;
- bh->bmh_YAspect=0;
- }
-
- static void GetMode(Object *obj,BitMapHeader *bh,Data *data)
- {
- ULONG mode;
- mode=BestModeID(
- BIDTAG_NominalWidth,bh->bmh_PageWidth,BIDTAG_NominalHeight,bh->bmh_PageHeight,
- BIDTAG_DesiredWidth,bh->bmh_Width,BIDTAG_DesiredHeight,bh->bmh_Height,
- BIDTAG_Depth,bh->bmh_Depth,
- BIDTAG_DIPFMustNotHave,DIPF_IS_DUALPF|DIPF_IS_PF2PRI|DIPF_IS_HAM|DIPF_IS_EXTRAHALFBRITE,TAG_END);
- SetDTAttrs(obj,0,0,PDTA_ModeID,mode,TAG_END);
- if(bh->bmh_Depth<=8) SetDTAttrs(obj,0,0,PDTA_NumColors,1<<bh->bmh_Depth,TAG_END);
- }
-
- static ULONG GetBody_Gray(JPEGDecHandle *jph,BitMapHeader *bh,BitMap *bm,Data *data)
- {
- ULONG error=0;
- UBYTE *buffer;
- RastPort rp;
- if(buffer=(UBYTE *)AllocBufferFromJPEG(jph,JPG_ScaleDenom,data->scale,TAG_END))
- {
- if(!DecompressJPEG(jph,JPG_DestRGBBuffer,buffer,JPG_ScaleDenom,data->scale,JPG_DCTMethod,data->dct,TAG_END))
- {
- Chunky2BitMap(buffer,0,0,bh->bmh_Width,bh->bmh_Height,bm,0,0,TAG_END);
- }
- else error=ERROR_NO_FREE_STORE;
- FreeJPEGBuffer(buffer);
- }
- else
- {
- BitMap *tbm;
- if(tbm=AllocBitMap(bh->bmh_Width,1,8,BMF_MINPLANES,bm))
- {
- RastPort trp;
- InitRastPort(&rp);
- InitRastPort(&trp);
- rp.BitMap=bm;
- trp.BitMap=tbm;
- JPEGINFO info={0,&rp,&trp,0,8,1};
- if(DecompressJPEG(jph,JPG_DecompressHook,getline,JPG_DecompressUserData,&info,JPG_ScaleDenom,data->scale,JPG_DCTMethod,data->dct,TAG_END)) error=ERROR_NO_FREE_STORE;
- FreeBitMap(tbm);
- }
- else error=ERROR_NO_FREE_STORE;
- }
- return error;
- }
-
- static ULONG GetBody_RGB(Object *obj,JPEGDecHandle *jph,BitMapHeader *bh,Data *data)
- {
- ULONG error=0;
- UBYTE *buffer;
- if(buffer=(UBYTE *)AllocBufferFromJPEG(jph,JPG_ScaleDenom,data->scale,TAG_END))
- {
- if(!DecompressJPEG(jph,JPG_DestRGBBuffer,buffer,JPG_ScaleDenom,data->scale,JPG_DCTMethod,data->dct,TAG_END))
- {
- DoMethod(obj,PDTM_WRITEPIXELARRAY,buffer,RECTFMT_RGB,bh->bmh_Width*3,0,0,bh->bmh_Width,bh->bmh_Height);
- }
- else error=ERROR_NO_FREE_STORE;
- FreeJPEGBuffer(buffer);
- }
- else
- {
- JPEGINFO info={obj,0,0,0,24,0};
- if(DecompressJPEG(jph,JPG_DecompressHook,getline,JPG_DecompressUserData,&info,JPG_ScaleDenom,data->scale,JPG_DCTMethod,data->dct,TAG_END)) error=ERROR_NO_FREE_STORE;
- }
- return error;
- }
-
- static ULONG GetBody_RGB8(Object *obj,JPEGDecHandle *jph,BitMapHeader *bh,BitMap *bm,Data *data)
- {
- ULONG error=0;
- UBYTE *rgb;
- if(rgb=(UBYTE *)AllocVec(4*bh->bmh_Width*bh->bmh_Height,MEMF_CLEAR))
- {
- JPEGINFO info={obj,0,0,rgb,bh->bmh_Depth,0};
- if(!DecompressJPEG(jph,
- JPG_DecompressHook,getline,
- JPG_DecompressUserData,&info,
- JPG_ScaleDenom,data->scale,
- JPG_DCTMethod,data->dct,
- TAG_END))
- {
- APTR rmh;
- if(rmh=CreateRMHandler(RND_MemType,RMHTYPE_POOL,TAG_END))
- {
- ULONG *palette;
- if(palette=CreatePalette(RND_RMHandler,rmh,TAG_END))
- {
- APTR hst;
- if(hst=CreateHistogram(RND_RMHandler,rmh,TAG_END))
- {
- if(AddRGBImage(hst,(ULONG *)rgb,bh->bmh_Width,bh->bmh_Height,TAG_END)==ADDH_SUCCESS)
- {
- ULONG numc;
- GetDTAttrs(obj,PDTA_NumColors,&numc,TAG_END);
- if(ExtractPalette(hst,palette,numc,TAG_END)==EXTP_SUCCESS)
- {
- UBYTE *chunky;
- if(chunky=(UBYTE *)AllocVec(bh->bmh_Width*bh->bmh_Height,0))
- {
- if(Render((ULONG *)rgb,bh->bmh_Width,bh->bmh_Height,chunky,palette,RND_DitherMode,data->dither,TAG_END)==REND_SUCCESS)
- {
- UBYTE *color;
- if(color=(UBYTE *)AllocVec((1<<bh->bmh_Depth)*4,0))
- {
- ExportPalette(palette,color,TAG_END);
- if(!(error=Colors2DT(obj,color))) Chunky2BitMap(chunky,0,0,bh->bmh_Width,bh->bmh_Height,bm,0,0,TAG_END);
- FreeVec(color);
- }
- else error=ERROR_NO_FREE_STORE;
- }
- else error=ERROR_NO_FREE_STORE;
- FreeVec(chunky);
- }
- else error=ERROR_NO_FREE_STORE;
- }
- else error=ERROR_NO_FREE_STORE;
- }
- else error=ERROR_NO_FREE_STORE;
- DeleteHistogram(hst);
- }
- else error=ERROR_NO_FREE_STORE;
- DeletePalette(palette);
- }
- else error=ERROR_NO_FREE_STORE;
- DeleteRMHandler(rmh);
- }
- else error=ERROR_NO_FREE_STORE;
- }
- else error=ERROR_NO_FREE_STORE;
- FreeVec(rgb);
- }
- else error=ERROR_NO_FREE_STORE;
- return error;
- }
-
- static ULONG GetPicture(IClass *cl,Object *obj)
- {
- ULONG error=0;
- long err;
- BPTR file;
- BitMapHeader *bh;
- GetDTAttrs(obj,DTA_Name,&bh,TAG_END);
- if(bh) SetDTAttrs(obj,0,0,DTA_ObjName,bh,TAG_END);
- GetDTAttrs(obj,DTA_Handle,&file,PDTA_BitMapHeader,&bh,TAG_END);
- if(bh)
- {
- JPEGDecHandle *jph;
- if(!file)
- {
- GetDTAttrs(obj,DTA_SourceType,&err,TAG_END);
- if(err!=DTST_RAM) return ERROR_REQUIRED_ARG_MISSING;
- else return 0;
- }
- if(!AllocJPEGDecompress(&jph,JPG_SrcFile,file,TAG_END))
- {
- UBYTE colorspace;
- ULONG w,h,bpp;
- Data *data=(Data *)INST_DATA(cl,obj);
- ReadPrefs(data);
- if(!GetJPEGInfo(jph,JPG_Width,&w,JPG_Height,&h,JPG_ColourSpace,&colorspace,JPG_BytesPerPixel,&bpp,JPG_ScaleDenom,data->scale,TAG_END))
- {
- BitMap *bm;
- switch(colorspace)
- {
- case JPCS_GRAYSCALE:
- FillBMHD(obj,bh,w,h,8);
- GetMode(obj,bh,data);
- if(bm=AllocBitMap(w,h,8,BMF_CLEAR|BMF_DISPLAYABLE|BMF_STANDARD,0))
- {
- Colors2DT(obj,0);
- SetDTAttrs(obj,0,0,DTA_NominalHoriz,w,DTA_NominalVert,h,PDTA_BitMap,bm,TAG_END);
- error=GetBody_Gray(jph,bh,bm,data);
- }
- else error=ERROR_NO_FREE_STORE;
- break;
- case JPCS_RGB:
- if(data->mode)
- {
- FillBMHD(obj,bh,w,h,24);
- SetDTAttrs(obj,0,0,DTA_ErrorNumber,&error,DTA_NominalHoriz,w,DTA_NominalVert,h,PDTA_SourceMode,PMODE_V43,PDTA_ModeID,0,TAG_END);
- if(!error) error=GetBody_RGB(obj,jph,bh,data);
- }
- else
- {
- FillBMHD(obj,bh,w,h,data->depth);
- GetMode(obj,bh,data);
- if(bm=AllocBitMap(w,h,data->depth,BMF_CLEAR|BMF_DISPLAYABLE|BMF_STANDARD,0))
- {
- SetDTAttrs(obj,0,0,DTA_NominalHoriz,w,DTA_NominalVert,h,PDTA_BitMap,bm,TAG_END);
- error=GetBody_RGB8(obj,jph,bh,bm,data);
- }
- else error=ERROR_NO_FREE_STORE;
- }
- break;
- default:
- error=ERROR_NOT_IMPLEMENTED;
- }
- }
- else error=DTERROR_INVALID_DATA;
- }
- else error=DTERROR_INVALID_DATA;
- }
- else error=ERROR_NO_FREE_STORE;
- return error;
- }
-
- static ULONG mNew(IClass *cl,Object *obj,opSet *msg)
- {
- TagItem *ti;
- if(ti=FindTagItem(DTA_SourceType,(((opSet *)msg)->ops_AttrList)))
- {
- if(ti->ti_Data!=DTST_FILE&&ti->ti_Data!=DTST_CLIPBOARD&&ti->ti_Data!=DTST_RAM)
- {
- SetIoErr(ERROR_OBJECT_WRONG_TYPE);
- return 0;
- }
- }
- if(obj==(Object *)cl)
- {
- if(obj=(Object *)DoSuperMethodA(cl,obj,Msg(msg)))
- {
- ULONG error;
- if(error=GetPicture(cl,obj))
- {
- SetIoErr(error);
- CoerceMethod(cl,obj,OM_DISPOSE);
- obj=0;
- }
- }
- }
- else
- {
- SetIoErr(ERROR_NOT_IMPLEMENTED);
- obj=0;
- }
- return ULONG(obj);
- }
-
- static ULONG mSet(IClass *cl,Object *obj,opSet *msg)
- {
- ULONG retval;
- if(retval=DoSuperMethodA(cl,obj,Msg(msg)))
- {
- RastPort *rp;
- if(rp=ObtainGIRPort(msg->ops_GInfo))
- {
- DoMethod(obj,GM_RENDER,msg->ops_GInfo,rp,GREDRAW_UPDATE);
- ReleaseGIRPort(rp);
- retval=0;
- }
- }
- return retval;
- }
-
- static ULONG mWrite(IClass *cl,Object *obj,dtWrite *msg)
- {
- return (msg->dtw_Mode==DTWM_IFF)?DoSuperMethodA(cl,obj,Msg(msg)):SaveJPEG(cl,obj,msg);
- }
-
- extern "C" ULONG Dispatcher(register __a0 IClass *cl,register __a2 Object *obj,register __a1 Msg msg)
- {
- ULONG retval;
- switch(msg->MethodID)
- {
- case OM_NEW:
- retval=mNew(cl,obj,(opSet *)msg);
- break;
- case OM_UPDATE:
- if(DoMethod(obj,ICM_CHECKLOOP)) break;
- case OM_SET:
- retval=mSet(cl,obj,(opSet *)msg);
- break;
- case DTM_WRITE:
- retval=mWrite(cl,obj,(dtWrite *)msg);
- break;
- default:
- retval=DoSuperMethodA(cl,obj,msg);
- }
- return retval;
- }
-
-