Saving 8bit Raw data as 8bit 256 color JPG no way

Windows specific forum
LiK137
Enthusiast
Enthusiast
Posts: 282
Joined: Wed Jun 23, 2010 5:13 pm

Saving 8bit Raw data as 8bit 256 color JPG no way

Post by LiK137 »

Hi,
Thanks to Rashad I've been able to Save 8bit Raw data as BMP but can't do the sabe for JPG

Code: Select all


Procedure AsciiBitBit(*Source, *Dest, memSize)
  Define lupBitBit
  For lupBitBit = 0 To memSize-1
    PokeA(*Dest+lupBitBit, PeekA(*Source+lupBitBit))
  Next
EndProcedure  

Procedure FlipRawRows(*RawData, w, h)  ;Applies or unapplies #PB_PixelFormat_ReversedY
  Protected *pbuf, *psrc, *ptmp, *pdst, i, width = w, height = h 
    *pbuf = *RawData
    *psrc = *pbuf
    *ptmp = AllocateMemory(width*height)
    If *ptmp
      *pdst = *ptmp + (width*height)-width
      For i = 0 To height-1
        CopyMemory(*psrc, *pdst, width)
        *pdst-width
        *psrc+width
      Next i
      CopyMemory(*ptmp, *pbuf, width*height)
      FreeMemory(*ptmp)                     
      ProcedureReturn *pbuf
    EndIf
    ProcedureReturn 0
EndProcedure

ProcedureDLL Save8bitImage(*RawData, w , h , filename$ = "", ColorMod = #Gray) 
  
  Define Bmp.BITMAP, BmiInfo.BITMAPINFOHEADER 
  
    With BmiInfo.BITMAPINFOHEADER 
      \biSize         = SizeOf(BITMAPINFOHEADER) 
      \biWidth        = w 
      \biHeight       = h 
      \biPlanes       = 1 
      \biBitCount     = 8 
    EndWith 
    Define sz_colorbits = BITMAP_GetWidthBytes(w, 8)*h 
    Define NumColors = 256
    If ColorMod = #Gray
      Define *colortable = GrayscaleTable()
    Else
      Define *colortable = ColorTable()
    EndIf  
    Define sz_image = SizeOf(BITMAPFILEHEADER) + SizeOf(BITMAPINFOHEADER) + NumColors*SizeOf(RGBQUAD) + sz_colorbits 
    Define *rawimage = AllocateMemory(sz_image) 
    Define *fileheader.BITMAPFILEHEADER = *rawimage 
    Define *header = *rawimage + SizeOf(BITMAPFILEHEADER) 
    With *fileheader 
      \bfType = $4D42 ; "BM" for Bit Map
      \bfSize = sz_image 
      \bfOffBits = SizeOf(BITMAPFILEHEADER) + SizeOf(BITMAPINFOHEADER) + NumColors*SizeOf(RGBQUAD) 
    EndWith 
    
  CopyMemory(BmiInfo, *header, SizeOf(BITMAPINFOHEADER)) 
  CopyMemory(*colortable, *rawimage + SizeOf(BITMAPFILEHEADER) + SizeOf(BITMAPINFOHEADER), NumColors*SizeOf(RGBQUAD)) 
  CopyMemory(*RawData, *rawimage + SizeOf(BITMAPFILEHEADER) + SizeOf(BITMAPINFOHEADER) + NumColors*SizeOf(RGBQUAD), sz_colorbits) 
  FreeMemory(*colortable) 
    define file = CreateFile(#PB_Any, filename$) 
    If file 
      WriteData(file,*rawimage,MemorySize(*rawimage)) 
      CloseFile(file) 
    EndIf 
    FreeMemory(*rawimage) 
    ProcedureReturn 1 
EndProcedure 

  Define *FlipImgData = AllocateMemory(w*h)
  If *FlipImgData
    AsciiBitBit(*ImgData, *FlipImgData, w*h)
    FlipRawRows(*FlipImgData, w, h)
    If Save8bitImage(*FlipImgData, w, h, -1, "c:\temp\"+rndFileName+".bmp")
      Debug "BMPSaveOK"
      If FileSize("c:\temp\"+rndFileName+".bmp") > 0
        Debug "BMPSizeOk"
        If SoftDPIset("c:\temp\"+rndFileName+".bmp", 500)
          Debug "BMPdpiOk"
        EndIf  
      EndIf 
    EndIf  
    FreeMemory(*FlipImgData)
  EndIf
Thank You very much
fabulouspaul
User
User
Posts: 34
Joined: Sun Nov 23, 2014 1:18 pm

Re: Saving 8bit Raw data as 8bit 256 color JPG no way

Post by fabulouspaul »

Haven't tried it, but why not taking the BMP-image from memory with CatchImage() and saving it as JPG?

You could change your ProcedureDLL Save8bitImage() like this (untested!)

Code: Select all

  Protected img_no 
  UseJPEGImageEncoder()
...
  CopyMemory(BmiInfo, *header, SizeOf(BITMAPINFOHEADER)) 
  CopyMemory(*colortable, *rawimage + SizeOf(BITMAPFILEHEADER) + SizeOf(BITMAPINFOHEADER), NumColors*SizeOf(RGBQUAD)) 
  CopyMemory(*RawData, *rawimage + SizeOf(BITMAPFILEHEADER) + SizeOf(BITMAPINFOHEADER) + NumColors*SizeOf(RGBQUAD), sz_colorbits) 

  img_no = CatchImage(#PB_Any, *rawimage)
  if img_no
    saveimage(img_no, filename$, #PB_ImagePlugin_JPEG)
  endif
...
LiK137
Enthusiast
Enthusiast
Posts: 282
Joined: Wed Jun 23, 2010 5:13 pm

Re: Saving 8bit Raw data as 8bit 256 color JPG no way

Post by LiK137 »

Thank You very much for reply.
But Saving by means of Purebasic is 24/32 bit only , no 8 bit
During SaveImage Automatically converted to 24
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Saving 8bit Raw data as 8bit 256 color JPG no way

Post by wilbert »

LiK137 wrote:But Saving by means of Purebasic is 24/32 bit only , no 8 bit
During SaveImage Automatically converted to 24
There is no such thing as a 256 color JPG. It doesn't exist.
Windows (x64)
Raspberry Pi OS (Arm64)
LiK137
Enthusiast
Enthusiast
Posts: 282
Joined: Wed Jun 23, 2010 5:13 pm

Re: Saving 8bit Raw data as 8bit 256 color JPG no way

Post by LiK137 »

Sorry, You are right about 256 color but what about 8bit greyscaled jpeg?
fabulouspaul
User
User
Posts: 34
Joined: Sun Nov 23, 2014 1:18 pm

Re: Saving 8bit Raw data as 8bit 256 color JPG no way

Post by fabulouspaul »

If PNG is a suitable image format for your demands, PB could deliver this out of the box...

The PB-Help says

Code: Select all

The depth in which to save the image. Valid values are 1, 4, 8, 24 and 32. The default value is the original image depth. For now, only BMP and PNG encoders support palletized image format (1, 4 or 8-bit).
Otherwise i would think you have to use an external image library that is able to write 8-bit greyscale JPG.
LiK137
Enthusiast
Enthusiast
Posts: 282
Joined: Wed Jun 23, 2010 5:13 pm

Re: Saving 8bit Raw data as 8bit 256 color JPG no way

Post by LiK137 »

Thank You for reply.
Only Jpeg is wanted as PureBasic naively encodes BMP in polarized.
I have reviewed all posts regarding GDI+ and FreeImage but unfortunately didn't find anything useful.
I have Jpeg images encoded (in Photoshop) but this not the solution I need.
fabulouspaul
User
User
Posts: 34
Joined: Sun Nov 23, 2014 1:18 pm

Re: Saving 8bit Raw data as 8bit 256 color JPG no way

Post by fabulouspaul »

I have reviewed all posts regarding GDI+ and FreeImage but unfortunately didn't find anything useful.
I have Jpeg images encoded (in Photoshop) but this not the solution I need.
You could try libjpeg (or libjpeg-turbo) and include the .dll to your project or you could call some external tool to convert your jpg (like irfanview) to 8 bit.
LiK137
Enthusiast
Enthusiast
Posts: 282
Joined: Wed Jun 23, 2010 5:13 pm

Re: Saving 8bit Raw data as 8bit 256 color JPG no way

Post by LiK137 »

Thanks to "fabulouspaul" for "libjpeg-turbo" hint, "wilbert" for "libjpeg-turbo" working sample code and the SDK developers, the problem with 8bit grey(gray)scale jpeg is solved finally.
Posting my update based on wilbert's thread:

Code: Select all

;{ PreStart
#lib_static = #False
#lib_ver = "2.0.1";"2.0.0";"1.5.3"
;}

;??? #define TJSCALED(dimension, scalingFactor) \ 
;   ((dimension * scalingFactor.num + scalingFactor.denom - 1) / \
;    scalingFactor.denom)

; tjtransform:
;???   Int (*customFilter) (short *coeffs, tjregion arrayRegion,
;                        tjregion planeRegion, int componentIndex,
;                        int transformIndex, struct tjtransform *transform);


;{ Const
#TJ_NUMSAMP = 6

Enumeration TJCS
  #TJCS_RGB = 0
  #TJCS_YCbCr
  #TJCS_GRAY
  #TJCS_CMYK
  #TJCS_YCCK
EndEnumeration  

#TJ_NUMERR = 2
Enumeration TJERR
  #TJERR_WARNING = 0
  #TJERR_FATAL
EndEnumeration

#TJ_NUMXOP = 8
Enumeration TJXOP
  #TJXOP_NONE = 0
  #TJXOP_HFLIP 
  #TJXOP_VFLIP
  #TJXOP_TRANSPOSE
  #TJXOP_TRANSVERSE
  #TJXOP_ROT90
  #TJXOP_ROT180
  #TJXOP_ROT270
EndEnumeration  

#TJXOPT_PERFECT     = 1
#TJXOPT_TRIM        = 2
#TJXOPT_CROP        = 4
#TJXOPT_GRAY        = 8
#TJXOPT_NOOUTPUT    = 16
#TJXOPT_PROGRESSIVE = 32
#TJXOPT_COPYNONE    = 64

#TJPF_UNKNOWN = -1
Enumeration
  #TJPF_RGB    
  #TJPF_BGR    
  #TJPF_RGBX    
  #TJPF_BGRX
  #TJPF_XBGR
  #TJPF_XRGB
  #TJPF_GRAY
  #TJPF_RGBA
  #TJPF_BGRA
  #TJPF_ABGR
  #TJPF_ARGB
  #TJPF_CMYK
EndEnumeration

Enumeration
  #TJSAMP_444    
  #TJSAMP_422    
  #TJSAMP_420  
  #TJSAMP_GRAY
  #TJSAMP_440
  #TJSAMP_411
EndEnumeration

Enumeration tjMCUWidth ;[TJ_NUMSAMP]
  #tjMCUWidth_1 = 8
  #tjMCUWidth_2 = 16
  #tjMCUWidth_3 = 16
  #tjMCUWidth_4 = 8
  #tjMCUWidth_5 = 8
  #tjMCUWidth_6 = 32
EndEnumeration  

Enumeration tjMCUHeight ;[TJ_NUMSAMP]
  #tjMCUHeight_1 = 8
  #tjMCUHeight_2 = 8
  #tjMCUHeight_3 = 16
  #tjMCUHeight_4 = 8
  #tjMCUHeight_5 = 16
  #tjMCUHeight_6 = 8
EndEnumeration

#TJ_NUMCS = 5
#TJ_NUMPF = 12

Enumeration tjRedOffset;[TJ_NUMPF]
  #tjRedOffset_1 = 0
  #tjRedOffset_2 = 2
  #tjRedOffset_3 = 0
  #tjRedOffset_4 = 2
  #tjRedOffset_5 = 3
  #tjRedOffset_6 = 1
  #tjRedOffset_7 = -1
  #tjRedOffset_8 = 0
  #tjRedOffset_9 = 2
  #tjRedOffset_10 = 3
  #tjRedOffset_11 = 1
  #tjRedOffset_12 = -1
EndEnumeration

Enumeration tjGreenOffset;[TJ_NUMPF]
  #tjGreenOffset_1 = 1
  #tjGreenOffset_2 = 1
  #tjGreenOffset_3 = 1
  #tjGreenOffset_4 = 1
  #tjGreenOffset_5 = 2
  #tjGreenOffset_6 = 2
  #tjGreenOffset_7 = -1
  #tjGreenOffset_8 = 1
  #tjGreenOffset_9 = 1
  #tjGreenOffset_10 = 2
  #tjGreenOffset_11 = 2
  #tjGreenOffset_12 = -1
EndEnumeration

Enumeration tjBlueOffset;[TJ_NUMPF] = {
  #tjBlueOffset_1 = 2
  #tjBlueOffset_2 = 0
  #tjBlueOffset_3 = 2
  #tjBlueOffset_4 = 0
  #tjBlueOffset_5 = 1
  #tjBlueOffset_6 = 3
  #tjBlueOffset_7 = -1
  #tjBlueOffset_8 = 2
  #tjBlueOffset_9 = 0
  #tjBlueOffset_10 = 1
  #tjBlueOffset_11 = 3
  #tjBlueOffset_12 = -1
EndEnumeration

Enumeration tjAlphaOffset;[TJ_NUMPF] = {
  #tjAlphaOffset_1 = -1
  #tjAlphaOffset_2 = -1
  #tjAlphaOffset_3 = -1
  #tjAlphaOffset_4 = -1
  #tjAlphaOffset_5 = -1
  #tjAlphaOffset_6 = -1
  #tjAlphaOffset_7 = -1
  #tjAlphaOffset_8 = 3
  #tjAlphaOffset_9 = 3
  #tjAlphaOffset_10 = 0
  #tjAlphaOffset_11 = 0
  #tjAlphaOffset_12 = -1
EndEnumeration

Enumeration tjPixelSize;[TJ_NUMPF] = {
  #tjPixelSize_1 = 3
  #tjPixelSize_2 = 3
  #tjPixelSize_3 = 4
  #tjPixelSize_4 = 4
  #tjPixelSize_5 = 4
  #tjPixelSize_6 = 4
  #tjPixelSize_7 = 1
  #tjPixelSize_8 = 4
  #tjPixelSize_9 = 4
  #tjPixelSize_10 = 4
  #tjPixelSize_11 = 4
  #tjPixelSize_12 = 4
EndEnumeration

#TJFLAG_BOTTOMUP      = 2
#TJFLAG_FASTUPSAMPLE  = 256
#TJFLAG_NOREALLOC     = 1024
#TJFLAG_FASTDCT       = 2048
#TJFLAG_ACCURATEDCT   = 4096
#TJFLAG_STOPONWARNING = 8192
#TJFLAG_PROGRESSIVE   = 16384

; /* Deprecated functions And macros */
#TJFLAG_FORCEMMX  = 8
#TJFLAG_FORCESSE  = 16
#TJFLAG_FORCESSE2 = 32
#TJFLAG_FORCESSE3 = 128

; /* Backward compatibility functions And macros (nothing To see here) */
#NUMSUBOPT       = #TJ_NUMSAMP
#TJ_444          = #TJSAMP_444
#TJ_422          = #TJSAMP_422
#TJ_420          = #TJSAMP_420
#TJ_411          = #TJSAMP_420
#TJ_GRAYSCALE    = #TJSAMP_GRAY

#TJ_BGR          = 1
#TJ_BOTTOMUP     = #TJFLAG_BOTTOMUP
#TJ_FORCEMMX     = #TJFLAG_FORCEMMX
#TJ_FORCESSE     = #TJFLAG_FORCESSE
#TJ_FORCESSE2    = #TJFLAG_FORCESSE2
#TJ_ALPHAFIRST   = 64
#TJ_FORCESSE3    = #TJFLAG_FORCESSE3
#TJ_FASTUPSAMPLE = #TJFLAG_FASTUPSAMPLE
#TJ_YUV          = 512
;}
;{ Struct
CompilerIf Defined(tjscalingfactor, #PB_Structure) = #False
Structure tjscalingfactor
  num.l
  denom.l
EndStructure
CompilerEndIf

CompilerIf Defined(tjregion, #PB_Structure) = #False
Structure tjregion
  x.l
  y.l
  w.l
  h.l
EndStructure
CompilerEndIf

CompilerIf Defined(tjtransform, #PB_Structure) = #False
Structure tjtransform
  r.tjregion
  op.l
  options.l
  *JPData
;   /**
;    * A callback function that can be used To modify the DCT coefficients
;    * after they are losslessly transformed but before they are transcoded To a
;    * new JPEG image.  This allows For custom filters Or other transformations
;    * To be applied in the frequency domain.
;    *
;    * @param coeffs pointer To an Array of transformed DCT coefficients.  (NOTE:
;    * this pointer is Not guaranteed To be valid once the callback returns, so
;    * applications wishing To hand off the DCT coefficients To another function
;    * Or library should make a copy of them within the body of the callback.)
;    *
;    * @param arrayRegion #tjregion Structure containing the width And height of
;    * the Array pointed To by <tt>coeffs</tt> As well As its offset relative To
;    * the component plane.  TurboJPEG implementations may choose To split each
;    * component plane into multiple DCT coefficient arrays And call the callback
;    * function once For each Array.
;    *
;    * @param planeRegion #tjregion Structure containing the width And height of
;    * the component plane To which <tt>coeffs</tt> belongs
;    *
;    * @param componentID ID number of the component plane To which
;    * <tt>coeffs</tt> belongs (Y, Cb, And Cr have, respectively, ID's of 0, 1,
;    * And 2 in typical JPEG images.)
;    *
;    * @param transformID ID number of the transformed image To which
;    * <tt>coeffs</tt> belongs.  This is the same As the index of the transform
;    * in the <tt>transforms</tt> Array that was passed To #tjTransform().
;    *
;    * @param transform a pointer To a #tjtransform Structure that specifies the
;    * parameters And/Or cropping region For this transform
;    *
;    * @return 0 If the callback was successful, Or -1 If an error occurred.
;    */
;???   Int (*customFilter) (short *coeffs, tjregion arrayRegion,
;                        tjregion planeRegion, int componentIndex,
;                        int transformIndex, struct tjtransform *transform);
EndStructure  
CompilerEndIf
;}
Macro TJPAD(width)
  (((width) + 3) & (~3))
EndMacro
CompilerIf #lib_static = #True
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    #LIBTURBO = "v"+#lib_ver+"/libjpeg-turbo/lib/turbojpeg-Static.lib"
  CompilerElseIf #PB_Compiler_Processor = #PB_Processor_x64
    #LIBTURBO = "v"+#lib_ver+"/libjpeg-turbo64/lib/turbojpeg-static.lib"
  CompilerEndIf
  
    Macro JPTpreInit()  
  
    ImportC #LIBTURBO
      tjAlloc(bytes)
      tjCompress2.l(handle, *srcBuf, width, pitch, height, pixelFormat, *p_jpegBuf, *jpegSize, jpegSubsamp, jpegQual, flags)
      tjDecompress2.l(handle, *jpegBuf, jpegSize, *dstBuf, width, pitch, height, pixelFormat, flags)
      tjDecompressHeader3.l(handle, *jpegBuf, jpegSize, *width, *height, *jpegSubsamp, *jpegColorspace)
      tjFree(*buffer)
      tjGetErrorStr()   
      tjInitCompress()
      tjInitDecompress()
      
    ; tjInitCompress();DLLEXPORT tjhandle 
    ; tjCompress2.l(handle, *srcBuf, width, pitch, height, pixelFormat, *p_jpegBuf, *jpegSize, jpegSubsamp, jpegQual, flags);DLLEXPORT int 
      tjCompressFromYUV.l(handle, *srcBuf, width, pad, height, subsamp, *p_jpegBuf, *jpegSize, jpegQual, flags);DLLEXPORT int 
      tjCompressFromYUVPlanes.l(handle, *p_srcPlanes, width, *strides, height, subsamp, *p_jpegBuf, *jpegSize, jpegQual, flags);DLLEXPORT int 
      tjBufSize.l(width, height, jpegSubsamp);DLLEXPORT unsigned long 
      tjBufSizeYUV2.l(width, pad, height, subsamp);DLLEXPORT unsigned long 
      tjPlaneSizeYUV.l(componentID, width, stride, height, subsamp);DLLEXPORT unsigned long 
      tjPlaneWidth.l(componentID, width, subsamp);DLLEXPORT int 
      tjPlaneHeight.l(componentID, height, subsamp);DLLEXPORT int 
      tjEncodeYUV3.l(handle, *srcBuf, width, pitch, height, pixelFormat, *dstBuf, pad, subsamp, flags);DLLEXPORT int 
      tjEncodeYUVPlanes.l(handle, *srcBuf, width, pitch, height, pixelFormat, *p_dstPlanes, *strides, subsamp, flags);DLLEXPORT int 
    ; tjInitDecompress.l();DLLEXPORT tjhandle 
    ; tjDecompressHeader3.l(handle, *jpegBuf, jpegSize, *width, *height, *jpegSubsamp, *jpegColorspace);DLLEXPORT int 
      tjGetScalingFactors.l(*numscalingfactors);DLLEXPORT tjscalingfactor *
    ; tjDecompress2.l(handle, *jpegBuf, jpegSize, *dstBuf, width, pitch, height, pixelFormat, flags);DLLEXPORT int 
      tjDecompressToYUV2.l(handle, *jpegBuf, jpegSize, *dstBuf, width, pad, height, flags);DLLEXPORT int 
      tjDecompressToYUVPlanes.l(handle, *jpegBuf, jpegSize, *p_dstPlanes, width, *strides, height, flags);DLLEXPORT int 
      tjDecodeYUV.l(handle, *srcBuf, pad, subsamp, *dstBuf, width, pitch, height, pixelFormat, flags);DLLEXPORT int 
      tjDecodeYUVPlanes.l(handle, *p_srcPlanes, *strides, subsamp, *dstBuf, width, pitch, height, pixelFormat, flags);DLLEXPORT int 
      tjInitTransform.l();DLLEXPORT tjhandle 
      tjTransform.l(handle, *jpegBuf, jpegSize, n, *p_dstBufs, *dstSizes, *transforms.tjtransform, flags);DLLEXPORT int 
      tjDestroy.l(handle);DLLEXPORT int 
    ; tjAlloc.l(bytes);DLLEXPORT unsigned char *
      tjLoadImage.l(*filename, *width, align, *height, *pixelFormat, flags);DLLEXPORT unsigned char *
      tjSaveImage.l(*filename, *buffer, width, pitch, height, pixelFormat, flags);DLLEXPORT int 
    ; tjFree(*buffer);DLLEXPORT void 
      tjGetErrorStr2.l(handle);DLLEXPORT char *
      tjGetErrorCode.l(handle);DLLEXPORT int 
    ; TJBUFSIZE.l(width, height);DLLEXPORT unsigned long 
    ; TJBUFSIZEYUV.l(width, height, jpegSubsamp);DLLEXPORT unsigned long 
      tjBufSizeYUV.l(width, height, subsamp);DLLEXPORT unsigned long 
      tjCompress.l(handle, *srcBuf, width, pitch, height, pixelSize, *dstBuf, *compressedSize, jpegSubsamp, jpegQual, flags);DLLEXPORT int 
      tjEncodeYUV.l(handle, *srcBuf, width, pitch, height, pixelSize, *dstBuf, subsamp, flags);DLLEXPORT int 
      tjEncodeYUV2.l(handle, *srcBuf, width, pitch, height, pixelFormat, *dstBuf, subsamp, flags);DLLEXPORT int 
      tjDecompressHeader.l(handle, *jpegBuf, jpegSize, *width, *height);DLLEXPORT int 
      tjDecompressHeader2.l(handle, *jpegBuf, jpegSize, *width, *height, *jpegSubsamp);DLLEXPORT int 
      tjDecompress.l(handle, *jpegBuf, jpegSize, *dstBuf, width, pitch, height, pixelSize, flags);DLLEXPORT int 
      tjDecompressToYUV.l(handle, *jpegBuf, jpegSize, *dstBuf, flags);DLLEXPORT int 
    ; tjGetErrorStr.l();DLLEXPORT char *
    EndImport
  EndMacro
CompilerElse
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    #LIBTURBO = "v"+#lib_ver+"/libjpeg-turbo/bin/turbojpeg.dll"
  CompilerElseIf #PB_Compiler_Processor = #PB_Processor_x64
    #LIBTURBO = "v"+#lib_ver+"/libjpeg-turbo64/bin/turbojpeg.dll"
  CompilerEndIf
    
  Procedure InitLibJPTurbo()
    Protected trjpLib = OpenLibrary(#PB_Any, #LIBTURBO)
    If trjpLib And IsLibrary(trjpLib)
    
      ProcedureReturn trjpLib
    
    EndIf
    ProcedureReturn #False
  EndProcedure
  
  Macro JPTpreInit()  
    
    trjpLib = InitLibJPTurbo()
      
    PrototypeC.l proto_tjAlloc(bytes) : Global tjAlloc.proto_tjAlloc = GetFunction(trjpLib,"tjAlloc")
    PrototypeC.l proto_tjCompress2(handle, *srcBuf, width, pitch, height, pixelFormat, *p_jpegBuf, *jpegSize, jpegSubsamp, jpegQual, flags) :  Global tjCompress2.proto_tjCompress2 = GetFunction(trjpLib,"tjCompress2")
    PrototypeC.l proto_tjDecompress2(handle, *jpegBuf, jpegSize, *dstBuf, width, pitch, height, pixelFormat, flags) : Global tjDecompress2.proto_tjDecompress2 = GetFunction(trjpLib,"tjDecompress2")
    PrototypeC.l proto_tjDecompressHeader3(handle, *jpegBuf, jpegSize, *width, *height, *jpegSubsamp, *jpegColorspace) : Global tjDecompressHeader3.proto_tjDecompressHeader3 = GetFunction(trjpLib,"tjDecompressHeader3")
    PrototypeC.l proto_tjFree(*buffer) : Global tjFree.proto_tjFree = GetFunction(trjpLib,"tjFree")
    PrototypeC.l proto_tjGetErrorStr() : Global tjGetErrorStr.proto_tjGetErrorStr = GetFunction(trjpLib,"tjGetErrorStr")
    PrototypeC.l proto_tjInitCompress() : Global tjInitCompress.proto_tjInitCompress = GetFunction(trjpLib,"tjInitCompress")
    PrototypeC.l proto_tjInitDecompress() : Global tjInitDecompress.proto_tjInitDecompress = GetFunction(trjpLib,"tjInitDecompress")
;   tjInitCompress();DLLEXPORT tjhandle 
;   tjCompress2.l(handle, *srcBuf, width, pitch, height, pixelFormat, *p_jpegBuf, *jpegSize, jpegSubsamp, jpegQual, flags);DLLEXPORT int 
    PrototypeC.l proto_tjCompressFromYUV(handle, *srcBuf, width, pad, height, subsamp, *p_jpegBuf, *jpegSize, jpegQual, flags) : Global tjCompressFromYUV.proto_tjCompressFromYUV = GetFunction(trjpLib,"tjCompressFromYUV")
    PrototypeC.l proto_tjCompressFromYUVPlanes(handle, *p_srcPlanes, width, *strides, height, subsamp, *p_jpegBuf, *jpegSize, jpegQual, flags) : Global tjCompressFromYUVPlanes.proto_tjCompressFromYUVPlanes = GetFunction(trjpLib,"tjCompressFromYUVPlanes")
    PrototypeC.l proto_tjBufSize(width, height, jpegSubsamp) : Global tjBufSize.proto_tjBufSize = GetFunction(trjpLib,"tjBufSize")
    PrototypeC.l proto_tjBufSizeYUV2(width, pad, height, subsamp) : Global tjBufSizeYUV2.proto_tjBufSizeYUV2 = GetFunction(trjpLib,"tjBufSizeYUV2")
    PrototypeC.l proto_tjPlaneSizeYUV(componentID, width, stride, height, subsamp) : Global tjPlaneSizeYUV.proto_tjPlaneSizeYUV = GetFunction(trjpLib,"tjPlaneSizeYUV")
    PrototypeC.l proto_tjPlaneWidth(componentID, width, subsamp) : Global tjPlaneWidth.proto_tjPlaneWidth = GetFunction(trjpLib,"tjPlaneWidth")
    PrototypeC.l proto_tjPlaneHeight(componentID, height, subsamp) : Global tjPlaneHeight.proto_tjPlaneHeight = GetFunction(trjpLib,"tjPlaneHeight")
    PrototypeC.l proto_tjEncodeYUV3(handle, *srcBuf, width, pitch, height, pixelFormat, *dstBuf, pad, subsamp, flags) : Global tjEncodeYUV3.proto_tjEncodeYUV3 = GetFunction(trjpLib,"tjEncodeYUV3")
    PrototypeC.l proto_tjEncodeYUVPlanes(handle, *srcBuf, width, pitch, height, pixelFormat, *p_dstPlanes, *strides, subsamp, flags) : Global tjEncodeYUVPlanes.proto_tjEncodeYUVPlanes = GetFunction(trjpLib,"tjEncodeYUVPlanes")
;   tjInitDecompress.l();DLLEXPORT tjhandle 
;   tjDecompressHeader3.l(handle, *jpegBuf, jpegSize, *width, *height, *jpegSubsamp, *jpegColorspace);DLLEXPORT int 
    PrototypeC.l proto_tjGetScalingFactors(*numscalingfactors) : Global tjGetScalingFactors.proto_tjGetScalingFactors = GetFunction(trjpLib,"tjGetScalingFactors")
;   tjDecompress2.l(handle, *jpegBuf, jpegSize, *dstBuf, width, pitch, height, pixelFormat, flags);DLLEXPORT int 
    PrototypeC.l proto_tjDecompressToYUV2(handle, *jpegBuf, jpegSize, *dstBuf, width, pad, height, flags) : Global tjDecompressToYUV2.proto_tjDecompressToYUV2 = GetFunction(trjpLib,"tjDecompressToYUV2")
    PrototypeC.l proto_tjDecompressToYUVPlanes(handle, *jpegBuf, jpegSize, *p_dstPlanes, width, *strides, height, flags) : Global tjDecompressToYUVPlanes.proto_tjDecompressToYUVPlanes = GetFunction(trjpLib,"tjDecompressToYUVPlanes")
    PrototypeC.l proto_tjDecodeYUV(handle, *srcBuf, pad, subsamp, *dstBuf, width, pitch, height, pixelFormat, flags) : Global tjDecodeYUV.proto_tjDecodeYUV = GetFunction(trjpLib,"tjDecodeYUV")
    PrototypeC.l proto_tjDecodeYUVPlanes(handle, *p_srcPlanes, *strides, subsamp, *dstBuf, width, pitch, height, pixelFormat, flags) : Global tjDecodeYUVPlanes.proto_tjDecodeYUVPlanes = GetFunction(trjpLib,"tjDecodeYUVPlanes")
    PrototypeC.l proto_tjInitTransform() : Global tjInitTransform.proto_tjInitTransform = GetFunction(trjpLib,"tjInitTransform")
    PrototypeC.l proto_tjTransform(handle, *jpegBuf, jpegSize, n, *p_dstBufs, *dstSizes, *transforms.tjtransform, flags) : Global tjTransform.proto_tjTransform = GetFunction(trjpLib,"tjTransform")
    PrototypeC.l proto_tjDestroy(handle) : Global tjDestroy.proto_tjDestroy = GetFunction(trjpLib,"tjDestroy")
;   tjAlloc.l(bytes);DLLEXPORT unsigned char *
    PrototypeC.l proto_tjLoadImage(*filename, *width, align, *height, *pixelFormat, flags) : Global tjLoadImage.proto_tjLoadImage = GetFunction(trjpLib,"tjLoadImage")
    PrototypeC.l proto_tjSaveImage(*filename, *buffer, width, pitch, height, pixelFormat, flags) : Global tjSaveImage.proto_tjSaveImage = GetFunction(trjpLib,"tjSaveImage")
;   tjFree(*buffer);DLLEXPORT void 
    PrototypeC.l proto_tjGetErrorStr2(handle) : Global tjGetErrorStr2.proto_tjGetErrorStr2 = GetFunction(trjpLib,"tjGetErrorStr2")
    PrototypeC.l proto_tjGetErrorCode(handle) : Global tjGetErrorCode.proto_tjGetErrorCode = GetFunction(trjpLib,"tjGetErrorCode")
;   TJBUFSIZE.l(width, height);DLLEXPORT unsigned long 
;   TJBUFSIZEYUV.l(width, height, jpegSubsamp);DLLEXPORT unsigned long 
    PrototypeC.l proto_tjBufSizeYUV(width, height, subsamp) : Global tjBufSizeYUV.proto_tjBufSizeYUV = GetFunction(trjpLib,"tjBufSizeYUV")
    PrototypeC.l proto_tjCompress(handle, *srcBuf, width, pitch, height, pixelSize, *dstBuf, *compressedSize, jpegSubsamp, jpegQual, flags) : Global tjCompress.proto_tjCompress = GetFunction(trjpLib,"tjCompress")
    PrototypeC.l proto_tjEncodeYUV(handle, *srcBuf, width, pitch, height, pixelSize, *dstBuf, subsamp, flags) : Global tjEncodeYUV.proto_tjEncodeYUV = GetFunction(trjpLib,"tjEncodeYUV")
    PrototypeC.l proto_tjEncodeYUV2(hande, *srcBuf, width, pitch, height, pixelFormat, *dstBuf, subsamp, flags) : Global tjEncodeYUV2.proto_tjEncodeYUV2 = GetFunction(trjpLib,"tjEncodeYUV2")
    PrototypeC.l proto_tjDecompressHeader(handle, *jpegBuf, jpegSize, *width, *height) : Global tjDecompressHeader.proto_tjDecompressHeader = GetFunction(trjpLib,"tjDecompressHeader")
    PrototypeC.l proto_tjDecompressHeader2(handle, *jpegBuf, jpegSize, *width, *height, *jpegSubsamp) : Global tjDecompressHeader2.proto_tjDecompressHeader2 = GetFunction(trjpLib,"tjDecompressHeader2")
    PrototypeC.l proto_tjDecompress(handle, *jpegBuf, jpegSize, *dstBuf, width, pitch, height, pixelSize, flags) : Global tjDecompress.proto_tjDecompress = GetFunction(trjpLib,"tjDecompress")
    PrototypeC.l proto_tjDecompressToYUV(handle, *jpegBuf, jpegSize, *dstBuf, flags) : Global tjDecompressToYUV.proto_tjDecompressToYUV = GetFunction(trjpLib,"tjDecompressToYUV")
;   tjGetErrorStr.l();DLLEXPORT char *
  EndMacro    
CompilerEndIf  
Macro JPTinit()
  JPTpreInit()
; TJPF from PB PixelFormat
Procedure TJPF_(Format)
  If Format & #PB_PixelFormat_32Bits_RGB
    ProcedureReturn #TJPF_RGBA
  ElseIf Format & #PB_PixelFormat_24Bits_RGB
    ProcedureReturn #TJPF_RGB
  ElseIf Format & #PB_PixelFormat_32Bits_BGR
    ProcedureReturn #TJPF_BGRA
  Else
    ProcedureReturn #TJPF_BGR
  EndIf
EndProcedure
Procedure.i CatchImage_(Image, *Memory, Size)
  Protected.i result, w, h, subs, cs, r, pf, flags
  If PeekL(*Memory) & $ffffff <> $ffd8ff
    ProcedureReturn CatchImage(Image, *Memory, Size)
  ElseIf tjDecompressHeader3(tjD, *Memory, Size, @w, @h, @subs, @cs) = 0 And w And h
    result = CreateImage(Image, w, h, 24)
    If result
      If Image = #PB_Any : Image = result : EndIf
      StartDrawing(ImageOutput(Image))
      pf = DrawingBufferPixelFormat() : flags = #TJFLAG_ACCURATEDCT
      If pf & #PB_PixelFormat_ReversedY : flags | #TJFLAG_BOTTOMUP : EndIf
      r = tjDecompress2(tjD, *Memory, Size, DrawingBuffer(), w, DrawingBufferPitch(), h, TJPF_(pf), flags)
      StopDrawing()
      If r
        FreeImage(Image) : result = 0
      EndIf
    EndIf    
  EndIf
  ProcedureReturn result
EndProcedure
Procedure LoadJPEG(Image, FileName.s)
  Protected.i result, fhandle, size, w, h, subs, cs, r, pf, flags, sig.l, *buffer.Long
  
  fhandle = ReadFile(#PB_Any, FileName)
  If fhandle
    size = Lof(fhandle)
    If size > 96
      sig = ReadLong(fhandle)
      If sig & $ffffff = $ffd8ff; possible jpeg
        *buffer = AllocateMemory(size, #PB_Memory_NoClear)
        If *buffer
          *buffer\l = sig
          ReadData(fhandle, *buffer + 4, size - 4)
          ; jpeg decompression
          If tjDecompressHeader3(tjD, *buffer, size, @w, @h, @subs, @cs) = 0 And w And h
            ; create image
            result = CreateImage(Image, w, h, 24)
            If result
              If Image = #PB_Any : Image = result : EndIf
              StartDrawing(ImageOutput(Image))
              pf = DrawingBufferPixelFormat() : flags = #TJFLAG_ACCURATEDCT
              If pf & #PB_PixelFormat_ReversedY : flags | #TJFLAG_BOTTOMUP : EndIf
              r = tjDecompress2(tjD, *buffer, size, DrawingBuffer(), w, DrawingBufferPitch(), h, TJPF_(pf), flags)
              StopDrawing()
              If r
                FreeImage(Image) : result = 0
              EndIf
            EndIf
          EndIf
          FreeMemory(*buffer) 
        EndIf
      EndIf
    EndIf
    CloseFile(fhandle)
  EndIf
  
  ProcedureReturn result  
EndProcedure
Procedure SaveJPEG(Image, FileName.s, quality = 95)
  Protected.i result, pf, flags, r, size, fhandle, *buffer
  If IsImage(Image) And StartDrawing(ImageOutput(Image))
    pf = DrawingBufferPixelFormat()
    If quality < 1 : quality = 1 : ElseIf quality > 100 : quality = 100 : EndIf
    If quality > 80 : flags = #TJFLAG_ACCURATEDCT : Else : flags = #TJFLAG_FASTDCT : EndIf
    If pf & #PB_PixelFormat_ReversedY : flags | #TJFLAG_BOTTOMUP : EndIf
    r = tjCompress2(tjC, DrawingBuffer(), OutputWidth(), DrawingBufferPitch(), OutputHeight(), TJPF_(pf), @*buffer, @size, #TJSAMP_444, quality, flags)
    StopDrawing()
    If r = 0
      fhandle = CreateFile(#PB_Any, FileName)
      If fhandle
        If WriteData(fhandle, *buffer, size) = size
          result = #True
        EndIf
        CloseFile(fhandle)
      EndIf
    EndIf
    tjFree(*buffer)
  EndIf
  ProcedureReturn result
EndProcedure
  
EndMacro  
  
CompilerIf #PB_Compiler_IsMainFile
; generate image data
  JPTinit()
  
  Dim ImageData.l(255, 255)
  
  For y = 0 To 255
    For x = 0 To 255
      ImageData(y, x) = x << 16 | y << 8 | (x ! y)
    Next
  Next

; write jpeg file

  Define tjC = tjInitCompress()
  
  *buffer = 0
  
; tjDecompressHeader3(handle, ?jpeg_start, ?jpeg_end - ?jpeg_start, @width, @height, @subsamp, @cs)
; *m = AllocateMemory(width * height * 4, #PB_Memory_NoClear)
; tjDecompress2(handle, ?jpeg_start, ?jpeg_end - ?jpeg_start, *m, width, 0, height, #TJPF_BGRX, 0)
; DataSection
;   jpeg_start:
;   IncludeBinary "test.jpg"
;   jpeg_end:
; EndDataSection  
  
  If tjCompress2(tjC, @ImageData(), 256, 1024, 256, #TJPF_GRAY, @*buffer, @size, #TJSAMP_GRAY, 95, #TJFLAG_ACCURATEDCT) = 0
    If CreateFile(0, "libturbojpeg_test.jpg")
      WriteData(0, *buffer, size)
      CloseFile(0)
    EndIf
    tjFree(*buffer)
  EndIf
CompilerEndIf  
Post Reply