September 26, 2020, 07:19:18 pm

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


Jpeg Image Width and Height

Started by GWS, April 16, 2010, 05:54:36 am

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

GWS

Hi folks,

I've looked all over the net and found several algorithms for getting the dimensions of a jpeg image - but they are in other assorted languages, and I can't get any of them to work ..  ::)

Does anyone have any solution to this ?

The jpeg format seems very unhelpful - you would think the size of the image would have been in the first few bytes of the file - but apparently not.  You have to read the whole file in, and then search sector by sector until you (hopefully) find the size data.

Nobody makes things easy anymore ..   ;D

best wishes, :)

Graham
Tomorrow may be too late ..

LarryMc

Graham

Back in 2002 TronDoc wrote some routines (GIFDim,JPGDim,PNGDim) that were handy for getting the sizes.
Jerry Meulver ran the code for the ONGDim back then.  Maybe he has a copy laying around.

LarryMc
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

GWS

April 16, 2010, 12:17:13 pm #2 Last Edit: April 16, 2010, 01:50:54 pm by GWS
Thanks Larry - the program names did the trick - I searched the old Pyxia Forum viewer and some code was still there ..  ;D

There's so much good stuff around.

I'll see how I get on now, and I'll post a bit of code if it works for my little application.

all the best, :)

Graham
Tomorrow may be too late ..

LarryMc

Graham
In the IB STD downloads over at CodingMonkeys there is the Archives that has all the source code for the above in it.

http://www.codingmonkeys.com/index.php?action=tpmod;dl=item105

LarryMc
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

GWS

April 20, 2010, 07:47:49 am #4 Last Edit: April 20, 2010, 08:05:41 am by GWS
Well, here's what I've done .. it's a long story, but I've been playing with Delphi, and managed to make a program to display images and be able to print them.

It was relatively easy in Delphi, because of all the professional components that are built in.  I like how it displayed images, and wondered if I could do the same in Creative ..  :P

Naturally, I needed to roll my own image handling, and finding the dimensions of images so that they could be scaled and displayed centrally in the window, was not easy.  Without the amazing pathfinding work of the much missed TronDoc, I don't think I could have managed it.

So here it is.  It only handles .bmp and .jpg images at the moment.  Right-clicking the mouse brings up a pop-up menu.

Code Select

' Creative Basic Image Viewer
' (for .jpg and .bmp files only at the moment).
' GWS - April 2010

def win: window
def wstyle,varL,varT,varW,varH,run : int
def image,iW,iH,w,h,clr:int
def i,pcx,pcy:int
def width,height,xpos,ypos:int
def a$,filename,filter : string
def buf[100]:istring
def scale,msw,msH:float
def f:file

declare sub Dimensions(filename as string)

autodefine "off"

getscreensize varW,varH
wstyle = @SIZE|@MINBOX|@MAXBOX

window win,-varW,0,varW,varH,wstyle,0,"Picture Viewer",main
setwindowcolor win,0xB19983

showwindow win, @swmaximized

MENU win, "T, File, 0, 0" ,  "I, Open, 0, 1" ,  "I, Print, 0 ,2", "I, Exit, 0, 3"
INSERTMENU win, 1,"T, Help, 0, 0", "I, About, 0, 4"

run = 1
waituntil run = 0
closewindow win
END

SUB main
select @CLASS
case @IDCLOSEWINDOW
run = 0
' clicking the Exit button ...
case @IDCONTROL
select @CONTROLID
case 1
run = 0
endselect
case @IDRBUTTONUP
   CONTEXTMENU win, @MOUSEX, @MOUSEY, "I,About,0,98","I,Exit,0,99"
case @IDMENUPICK
select @MENUNUM
case 1
' clear screen ..
SETWINDOWCOLOR win,0xB19983
filter = "Jpeg|*.jpg|Bitmap|*.bmp||"
filename = lcase$(filerequest("Images",0,1,filter))
image = LOADIMAGE (filename, @IMGSCALABLE)
SETCAPTION win, "Picture Viewer - " + filename
' for .bmp files ..
if right$(filename,3) = "bmp"
openfile(f,filename,"R")
read f,buf
closefile f
' get the bitmap dimensions ..
if (asc(buf[0])=66) & (asc(buf[1])=77)
width = asc(buf[18])+ asc(buf[19])*256
height = asc(buf[22]) + asc(buf[23])*256
endif
endif
' for .jpg files ..
if right$(filename,3) = "jpg"
' Get Width and Height of a Jpeg file ..
Dimensions(filename)
endif
' calculate scaling factor for full screen display ..
msW = varW / width
msH = varH / height
if msW > msH
scale = msH
else
scale = msW
endif
' don't use the whole screen ..
scale = 0.95 * scale
iW = width * scale
iH = height * scale
if (varW - iW)
xpos = (varW - iW)/2
else
xpos = 0
endif
if ((varH - iH)/2 > 20)
ypos = (varH - iH)/2 - 20
else
ypos = 0
endif

' display the image ..
SHOWIMAGE win, image, @IMGSCALABLE, xpos, ypos ,iW, iH

case 3
case 99
run = 0
case 4
case 98
a$ = "Image Viewer" + chr$(10) + "Version 1.0"
MESSAGEBOX win,a$,"Creative Basic" ,0|0x40
case 2
PRINTWINDOW win
endselect
endselect
RETURN
END

sub Dimensions(filename)
' Subroutine for Jpeg file dimensions, based on a TronDoc routine - 2002 ..
' (amended to work on an array buffer in memory rather than on the image file directly).
def f:bfile
def flen,p:INT
def segLen:int
def FF,D8,D9,C0,E0,C2:CHAR

def jfif$:STRING

FF=CHR$(255)
D8=CHR$(216)
D9=CHR$(217)
E0=CHR$(224)
C0=CHR$(192)
C2=CHR$(194)

' some jpeg file markers ..
' JFIF JPEG = FFD8
' SoF0 tag = FFC0
' SoF2 tag = FFC2

' read in the image file ..
if(OPENFILE(f,filename,"R") = 0)
flen = LEN(f)
def buf[flen+1]: char
read(f,buf)
closefile f

' go to end of file and check for End of Image EOI (FFD9)..
if (buf[flen-2]=FF) & (buf[flen-1]=D9)
' back to start of file ..
p=0
' check for start of image (FFD8) ..
if (buf[p]=FF) & (buf[p+1]=D8)
' check for JFIF APP0 segment ..
if (buf[p+2]=FF) & (buf[p+3]=E0)
' move to start of APPO segment
p=4
' calculate segment length ..
seglen = asc(chr$(buf[p]))*256 + ASC(CHR$(buf[p+1]))
JFIF$=CHR$(buf[p+2])+CHR$(buf[p+3])+CHR$(buf[p+4])+CHR$(buf[p+5])+CHR$(buf[p+6])
if (JFIF$="JFIF")
' JFIF stringZ found
' Now we can look for Start of frame zero ..
' Move to next segment .. (current p + segment length) = (4 + 16) = 20
p = 20

LABEL FindSoFn

if (buf[p]=FF)&((buf[p+1]=C2)|(buf[p+1]=C0))
' found SoF0 (Start of Frame Zero)
' Skip 3 Bytes (Frame Length[2] and Sample Precision[1])
height=256*ASC(CHR$(buf[p+5]))+ASC(CHR$(buf[p+6]))
width=256*ASC(CHR$(buf[p+7]))+ASC(CHR$(buf[p+8]))
else
' SoF0 (Start of Frame Zero) not found
' Calculate Segment Length ..
segLen=256*ASC(chr$(buf[p+2]))+ASC(chr$(buf[p+3]))
' position at next frame ..
p = p + 2 + seglen
if p > flen
MESSAGEBOX win,"Error finding SoFn","Error"
CLOSEFILE f
END
endif
GOTO FindSoFn
endif
else
' JFIF stringZ not found
MESSAGEBOX win,"JFIF stringZ not found","Error"
endif
else
' JFIF APP0 segment not found
MESSAGEBOX win,"JFIF APP0 not found","Error"
endif
else
' JPEG SOI not found
MESSAGEBOX win,"SOI not found","Error"
endif
else
' JPEG EOI not found
MESSAGEBOX win,"EOI not found","Error"
endif
CLOSEFILE f

return



I nearly forgot to mention, that the main difference in my jpg dimension routine from the one TronDoc developed, is that my approach was to read the whole file into an array that can be searched for segment flags - whereas TronDoc chose to delve into the .jpg file on disk, which of course meant a lot of seeking and reading operations ..  ;D

Hope you find it interesting ..

all the best, :)

Graham
Tomorrow may be too late ..

aurelCB

Hi Graham..
I dont get it where is rusult of dimensions ???
forum for hobby programming:<br />https://aurelsoft.ucoz.com

GWS

Hi Aurel,

The width and height for .jpg files are calculated in the middle of the Dimensions subroutine, and since they are global variables, the values are then used in the main program to scale the images.

Bitmap dimensions are calculated in the main program under the 'menupick' event handler, and again used to scale .bmp images.

If you wanted a utility to just show the dimensions for any given image, you could pick out the Dimensions subroutine, and have another subroutine with the few lines of code for Bitmaps.

I was mainly interested in the whole program to display and print images, so the calculation bits are just built-in ..

best wishes, :)

Graham 
Tomorrow may be too late ..

GWS

Just thinking, some folk may not have Creative loaded, so here is the .exe version to try the viewer out ..  :)

best wishes,

Graham
Tomorrow may be too late ..

GWS

Here are a few images to try it out on ..  :)

All images are scaled to fit the client area of the window - so the effect (depending on the quality of the image) can be impressive.
Nothing quite like a fullscreen image to knock you back in your seat with a Wow !! effect ..  ;D

I'm also surprised how a pop-up menu from a right-button mouse click, can be used to enhance functionality of a program.  I can't remember ever using the facility before.  I didn't even remember Creative could do it. ::)

I'd never used the PrintWindow command either - that works pretty well.

All in all, a quite satisfying project - and a useful image viewing tool as a result.

best wishes, :)

Graham
Tomorrow may be too late ..

aurelCB

Graham i really dont understand and dont see anywhere in
picture viewer window results of width & heigth?
For example i open image 'monet' with your program and program show picture corectly but
where is width & heigth?
Explorer show 400x378, where is this data presented?
forum for hobby programming:<br />https://aurelsoft.ucoz.com

Egil

Aurel:
The data is not presented on screen, but instead is used to do the scaling calculations to keep the picture whithin the borders of your screen.

Graham:
Is there a way in CB to retrieve clientwith and clientheight instead of dimensions for the whole screen, as you do in your program?


Egil
Support Amateur Radio  -  Have a ham  for dinner!

GWS

Hello Egil ..  :)

Yep, you can use :

GETCLIENTSIZE window | dialog,varL,varT,varW,varH

which will return the size of the drawing area of the window in the variables specified. L and T will always be 0 with this function. Variables must be of type INT.

Perhaps I should have used that actually - thanks for pointing it out ..  :)
That's why in the code, I sort of centred the images vertically, but raised them 20 pixels because I felt they were showing too low after allowing for the menu bar.

I think it looks OK though.

Aurel> no, I didn't actually display the size 'cos I only needed it to centre the images - I wasn't particularly interested in the sizes themselves.  The values could easily be added to the caption bar after the image name, if you were interested in that.

The key point for me, was that it was possible to produce a program with the same functionality as the very pricey Delphi.

best wishes, :)

Graham

Tomorrow may be too late ..

Egil

Thanks Graham!
I couldn't get GETCLIENTSIZE to work... when I check my file now I found a typo :-[

By the way, its nice to see that you havent totally "bowed out". But then it's difficult to teach an old dog to stop barking, I guess.

73' Egil
Support Amateur Radio  -  Have a ham  for dinner!

GWS

He .. He ! .. it's hard to stop programming .. like it's hard to stop riding motorbikes ..  ;D

I shall just fall off one day I suppose, with a smile on my face ..

best wishes,

Graham
Tomorrow may be too late ..