Compress and timestamp your pictures to gain disk space


I was running out of space again on my notebook. As years go by, digital cameras can take pictures with more megapixels, but that means they take up more space.


 


Thus my pictures from 10 years ago are much smaller than this year’s.


 


Since I have multiple copies of my picture collection (28,000!) I didn’t mind modifying the notebook’s copy. Also, since the notebook resolution is 1400 X 1050, and I only ever display the notebook pictures on the notebook screen, the camera picture’s resolution 3072 X 2074 (Canon Powershot SD800) included more info than I needed.


 


The code resulted in most pictures compressing about 80%! You can vary the quality parameter and try it yourself. Also, my disk contains all the movies taken by the camera too, and these aren’t touched by the code.


 


So I ran the code below and gained 5 Gigabytes of storage! Not bad.


 


The code uses the GDIPlus class library to load, compress and store the file. This changes the file timestamp, so the code also preserves the original timestamp.


 


See also:


 


Recompress your digital pictures to save space


Resize your pictures for your phone or pocket pc


Timestamp digital pictures


 


 


 


cRoot=ADDBS(“d:\pictures\2006\”)


recurdir(cRoot)


?“Done”,DATETIME()


PROCEDURE recurdir(cBasePath)


          LOCAL n,i


          LOCAL aa[1]


          ?cbasePath


          n=ADIR(aa,cBasePath+“*.*”,“D”)


 


          FOR i = 1 TO n


                   IF “D”$aa[i,5]


                             IF LEFT(aa[i,1],1)<>“.”


                                      recurdir(cBasePath+aa[i,1]+“\”)


                             ENDIF


                   ELSE


                             IF LOWER(JUSTEXT(aa[i,1]))=“jpg”


                                      recompress(cBasePath+aa[i,1])


                                      retimestamp(“d:\t.jpg”,CTOT(DTOC(aa[i,3])+” “+aa[i,4]))


                                      COPY FILE d:\t.jpg TO (cBasePath+aa[i,1])


                             ENDIF


                   ENDIF


          ENDFOR


          RETURN


         


 


PROCEDURE recompress(cPict as String)


          LOCAL aa[1]


          cOutfile=“d:\t.jpg”


          LOCAL oImage as gpImage OF (HOME()+“ffc\_gdiplus”)


          oImage=NEWOBJECT(“gpImage”,HOME()+“ffc\_gdiplus”,“”,cpict)


          oImage.SaveToFile(cOutfile,“image/jpeg”,“Quality=20”)


          ADIR(aa,cOutfile)


          nSizeNew=aa[1,2]


          ADIR(aa,cPict)


          nSizeOrig=aa[1,2]


          ?cPict


          ??” Orig Size = “,TRANSFORM(nSizeOrig,“999,999,999”)


          ??” New Size = “,TRANSFORM(nSizeNew,“999,999,999”)


*        ??” # bytes smaller = “, TRANSFORM(nSizeOrig – nSizeNew,”999,999,999”)


          ??” # times smaller”, TRANSFORM(nSizeOrig / nSizeNew)


          ??” % savings=”, TRANSFORM(100*(nSizeOrig – nSizeNew)/nSizeOrig )


          *! &cOutfile


RETURN


 


 


 


 


*From WINNT.H:


#define FILE_SHARE_READ                 0x00000001 


#define FILE_SHARE_WRITE                0x00000002 


#define FILE_SHARE_DELETE               0x00000004 


#define FILE_ATTRIBUTE_READONLY             0x00000001 


#define FILE_ATTRIBUTE_HIDDEN               0x00000002 


#define FILE_ATTRIBUTE_SYSTEM               0x00000004 


#define FILE_ATTRIBUTE_DIRECTORY            0x00000010 


#define FILE_ATTRIBUTE_ARCHIVE              0x00000020 


#define FILE_ATTRIBUTE_DEVICE               0x00000040 


#define FILE_ATTRIBUTE_NORMAL               0x00000080 


#define FILE_ATTRIBUTE_TEMPORARY            0x00000100 


#define FILE_ATTRIBUTE_SPARSE_FILE          0x00000200 


#define FILE_ATTRIBUTE_REPARSE_POINT        0x00000400 


#define FILE_ATTRIBUTE_COMPRESSED           0x00000800 


#define FILE_ATTRIBUTE_OFFLINE              0x00001000 


#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED  0x00002000 


#define FILE_ATTRIBUTE_ENCRYPTED            0x00004000 


#define FILE_WRITE_ATTRIBUTES                                0x100


#define GENERIC_WRITE     (0x40000000)


#define GENERIC_READ      (0x80000000)


 


 


*From winbase.h:


#define CREATE_NEW          1


#define CREATE_ALWAYS       2


#define OPEN_EXISTING       3


#define OPEN_ALWAYS         4


#define TRUNCATE_EXISTING   5


 


PROCEDURE ReTimeStamp(cFilename as string, dt as Datetime)


                   DECLARE integer CreateFile in win32api string, integer dwDesiredAccess, integer dwShareMode, integer security, ;


                             integer dwCreationDisposition, integer FlagsAttrs, integer hTemplate


                   DECLARE INTEGER CloseHandle in win32api integer hFile


                   DECLARE integer SystemTimeToFileTime IN WIN32API string , string @


                   DECLARE INTEGER SetFileTime IN kernel32;


                             INTEGER hFile, STRING lpCreationTime,;


                             STRING lpLastAccessTime, STRING lpLastWriteTime


                   DECLARE INTEGER SystemTimeToFileTime IN kernel32;


                             STRING lpSystemTime, STRING @lpFileTime


                   DECLARE INTEGER LocalFileTimeToFileTime IN kernel32;


                             STRING lpLocalFileTime, STRING @lpFileTime


                   DECLARE integer GetLastError in win32api


 


                   cFileTime = SPACE(8)


                   cSysTime=BINTOC(YEAR(dt),“2rs”) + ;


                                      BINTOC(MONTH(dt),“2rs”) + ;


                                      BINTOC(DOW(dt,0),“2rs”) + ;


                                      BINTOC(DAY(dt),“2rs”) + ;


                                      BINTOC(HOUR(dt),“2rs”) + ;


                                      BINTOC(MINUTE(dt),“2rs”) + ;


                                      REPLICATE(CHR(0),4)


                   SystemTimeToFileTime(cSysTime, @cFileTime)


 


                   LocalFileTimeToFileTime(cFileTime, @cFileTime)


 


                   hFile = CreateFile(cFilename, GENERIC_WRITE+GENERIC_READ,FILE_SHARE_READ, 0, OPEN_EXISTING, 0,0)


                   SetFileTime(hFile , cFileTime, cFileTime,cFileTime)


                   CloseHandle(hFile)


 


RETURN


 


 

Comments (3)

  1. Mike says:

    It’s nice to see you’re still using the FOX to do these type of things. I was beginning to think that you’d abandoned the "red head stepchild".

  2. Michael Schwing says:

    Yepp, i aplaude this too. There is nothing so powerful and yet so simple to program away on nifty little problem-solvers like VFP…

    Fox rocks!!!

    Thanks Calvin for not leaving us totaly alone :-)