How to: Create an ISO image of directories in Linux

I ripped some DVDs I own the other day as I wanted to create a back-up for the kids travel DVD players (so the originals don’t get scratched and trashed on the road), only the DVDs themselves were DVD-9’s (so single-sided dual-layer with a capacity of up to 8.54GB) while I can only write DVD-5’s (single-sided single layer with a capacity of up to 4.7GB) – this isn’t a big problem as I compressed them down to fit using Handbrake and elements of Shetboy’s meticulously crafted AVI to DVD technique. However, both Brasero and GnomeBaker would flat out refuse to burn Video projects – they’d just choke on the folder containing the AUDIO_TS and VIDEO_TS folders – so why not covert the directory including the *_TS folders to an ISO and burn that? No reason why not! Let’s get it done! =P

Making the ISO

Once you’ve got a folder structure containing the AUDIO_TS folder (which is empty) and the VIDEO_TS folder (which contains your .BUP, .IFO and .VOB files), just run the following command to generate your ISO:

mkisofs -o ISO_FILENAME -V LABEL -r SOURCE_DIRECTORY

So, for example, you might use the following command to create an ISO of the directory containing the *_TS folders for the film Avatar:

mkisofs -o ~/AvatarDVD.iso -V Avatar -r ~/dvdprep/Avatar/

Once you hit return, you’ll see something like the following output:

I: -input-charset not specified, using utf-8 (detected in locale settings)
  0.22% done, estimate finish Wed Jul 27 12:30:27 2011
 
..... all the rest ......
 
 99.96% done, estimate finish Wed Jul 27 12:27:58 2011
Total translation table size: 0
Total rockridge attributes bytes: 1353
Total directory bytes: 4096
Path table size(bytes): 42
Max brk space used 21000
2275896 extents written (4445 MB)

Measure Twice, Cut Once

If you wanted to make sure you got it right, as in, you ONLY have the *_TS folders in the iso, not the top level folder containing those two folders also, then just open the created iso file with Archive Manager and take a look, or mount it to a folder with:

mkdir test
sudo mount -o loop -t iso9660 ./AvatarDVD.iso ./test
ls test
 
[ which should show "AUDIO_TS  VIDEO_TS" ]
 
sudo umount ./test

When you’re happy with the iso, burn it with your burning software of choice and you’re all sorted!

Cheers!

Single-Call OpenGL Texture Loader in DevIL

I’ve been playing around with the DevIL image loading library today, and it has a command to load an image and assign it to an OpenGL texture in one fell swoop like this:

GLuint textureHandle = ilutGLLoadImage("some-picture.jpg");

Only I’m damned if I could get it to work, through I could take the long route and get DevIL to load/bind textures just fine, so I went and wrote my own version of ilutGLLoadImage, which works wonderfully =D

OpenGL DevIL Image Loader

Here’s the code:

  1. // Function load a image, turn it into a texture, and return the texture ID as a GLuint for use
  2. GLuint loadImage(const char* theFileName)
  3. {
  4. 	ILuint imageID;				// Create an image ID as a ULuint
  5.  
  6. 	GLuint textureID;			// Create a texture ID as a GLuint
  7.  
  8. 	ILboolean success;			// Create a flag to keep track of success/failure
  9.  
  10. 	ILenum error;				// Create a flag to keep track of the IL error state
  11.  
  12. 	ilGenImages(1, &imageID); 		// Generate the image ID
  13.  
  14. 	ilBindImage(imageID); 			// Bind the image
  15.  
  16. 	success = ilLoadImage(theFileName); 	// Load the image file
  17.  
  18. 	// If we managed to load the image, then we can start to do things with it...
  19. 	if (success)
  20. 	{
  21. 		// If the image is flipped (i.e. upside-down and mirrored, flip it the right way up!)
  22. 		ILinfo ImageInfo;
  23. 		iluGetImageInfo(&ImageInfo);
  24. 		if (ImageInfo.Origin == IL_ORIGIN_UPPER_LEFT)
  25. 		{
  26. 			iluFlipImage();
  27. 		}
  28.  
  29. 		// Convert the image into a suitable format to work with
  30. 		// NOTE: If your image contains alpha channel you can replace IL_RGB with IL_RGBA
  31. 		success = ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE);
  32.  
  33. 		// Quit out if we failed the conversion
  34. 		if (!success)
  35. 		{
  36. 			error = ilGetError();
  37. 			std::cout << "Image conversion failed - IL reports error: " << error << " - " << iluErrorString(error) << std::endl;
  38. 			exit(-1);
  39. 		}
  40.  
  41. 		// Generate a new texture
  42. 		glGenTextures(1, &textureID);
  43.  
  44. 		// Bind the texture to a name
  45. 		glBindTexture(GL_TEXTURE_2D, textureID);
  46.  
  47. 		// Set texture clamping method
  48. 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  49. 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  50.  
  51. 		// Set texture interpolation method to use linear interpolation (no MIPMAPS)
  52. 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  53. 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  54.  
  55. 		// Specify the texture specification
  56. 		glTexImage2D(GL_TEXTURE_2D, 				// Type of texture
  57. 					 0,				// Pyramid level (for mip-mapping) - 0 is the top level
  58. 					 ilGetInteger(IL_IMAGE_FORMAT),	// Internal pixel format to use. Can be a generic type like GL_RGB or GL_RGBA, or a sized type
  59. 					 ilGetInteger(IL_IMAGE_WIDTH),	// Image width
  60. 					 ilGetInteger(IL_IMAGE_HEIGHT),	// Image height
  61. 					 0,				// Border width in pixels (can either be 1 or 0)
  62. 					 ilGetInteger(IL_IMAGE_FORMAT),	// Format of image pixel data
  63. 					 GL_UNSIGNED_BYTE,		// Image data type
  64. 					 ilGetData());			// The actual image data itself
  65.  	}
  66.   	else // If we failed to open the image file in the first place...
  67.   	{
  68. 		error = ilGetError();
  69. 		std::cout << "Image load failed - IL reports error: " << error << " - " << iluErrorString(error) << std::endl;
  70. 		exit(-1);
  71.   	}
  72.  
  73.  	ilDeleteImages(1, &imageID); // Because we have already copied image data into texture data we can release memory used by image.
  74.  
  75. 	std::cout << "Texture creation successful." << std::endl;
  76.  
  77. 	return textureID; // Return the GLuint to the texture so you can use it!
  78. }

This means that if I had a picture called SpringLandscape.jpg in the same folder as my code, I could bind it to a texture like this:

GLuint textureHandle = loadImage("SpringLandscape.jpg");

Ha! I’m getting the hang of this coding lark… =P

Here’s some complete example code to get you up and running: DevIL-Image-Loader.cpp

Update 11/2010: I had a think about this the next day and decided I wanted the best quality filtering available (which is MipMaps using the GL_LINEAR_MIPMAP_LINEAR function), so to do this you can replace lines 51 to 53 with:

// Set texture interpolation method to the highest visual quality it can be:
// GL_LINEAR_MIPMAP_LINEAR for minification - i.e. trilinear filtering
// GL_LINEAR for magnification (choices are either GL_NEAREST or GL_LINEAR - we do not use any MIPMAP settings for magnification!!
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

And then straight after the glTexImage2D statement, add this line:

glGenerateMipmap(GL_TEXTURE_2D); // Note: This requires OpenGL 3.0 or higher

You’re going to have to abide by that caveat though and use GLEW or something to make the extension available to you, I’d suggest putting something like this into your code immediately after initialising your OpenGL context:

//  ----- Initialise GLEW -----
 
GLenum err = glewInit();
if (GLEW_OK != err)
{
	cout << "GLEW initialisation error: " << glewGetErrorString(err) << endl;
	exit(-1);
}
cout << "GLEW intialised successfully. Using GLEW version: " << glewGetString(GLEW_VERSION) << endl;

Cheers!

Update 09/2011: To use any DevIL functionality in your C++ project, you need to link in libIL, libILU and libILUT (in that order), and then initialise DevIL before you use it with:

	 //  ----- Initialise DevIL -----
	ilutRenderer(ILUT_OPENGL);
	ilInit();
	iluInit();
	ilutInit();
	ilutRenderer(ILUT_OPENGL);

You either have to specify your renderer before or after initialisation, and I don’t know which, so I just call it twice and don’t worry about it. If you know definitively whether it should be called before or after the il/ilu/ilut initialisation calls then share the wealth, bubba ;)

How To: Convert .WBFS Image Files to .ISO Images

Update: You can convert compressed ISO images (.ciso files) using this method, too…

If you need to translate a Wii DVD image from the newer .WBFS format (which has lovely sparce-file support) to an old-school .ISO image, well you can jolly well do so with Wii Backup Manager! Now, WBM is a really useful program so congrats to the author (xzxero) – but it uses non-standard GUI elements in that it uses what looks like the category list as a second main-menu, and this makes it a little non-intuitive to use. But in fairness to the author, the download page has a tutorial (which I didn’t find until after completing this post!). Still, it’s easy enough once you’ve figured that out. The entire conversion process goes like this:

1.) Grab yourself a copy of Wii Backup Manager. Version v0.3.5 beta 1 is the most recent version available at the time of writing, and although it’s Win32 only, it works fine in VirtualBox…

2.) Extract and launch it

Wii Backup Manager

3.) From the Files tab, click on what looks like the Add category title, select Files and go pick a .WBFS image from the navigation dialogue box

Wii Backup Manager - Add Files

4.) Still in the Files tab, tick the checkbox to the left of your .wbfs image, and then click on what looks like the Transfer category title and select ISO..

Wii Backup Manager - Transfer Files

5.) Pick where you want the converted .ISO file to be created and click the [OK] button

Wii Backup Manager - Place ISO

That’s it – job done! Transfer your ISO to your WBFS formatted USB drive and launch it as you normally would via USBLoaderGX or whatever your poison is… :)
Flattr this

How To: Scroll a Web-Page Background using JavaScript

Update: As per request, modified to move the background in any direction and at any speed you’d like – all you have to do is change the vertSpeed, horizSpeed, and updateDelay variables to values of your choice! Oh, and I fixed up the jitter-on-wrap-around properly to use a better way of constraining the offsets which caters for all directions without letting the offsets hit any numerical limits.

I’m teaching a course titled Produce and Manipulate Digital Images at the moment, which along with the photography and photoshop type elements you’d expect, has to include an assignment for the students to incorporate digital photography into a multimedia sequence. I can get them to do the sequence in anything I deem appropriate: Flash, JavaScript, OpenGL if I wanna.. But considering the course after this (for this particular class) is on Multimedia Web Design, I thought maybe it might be an idea to do it in JavaScript, so I had a look around for JavaScript image manipulation and found this background image scroller (link now dead unfortunately).

Only it was a bit knackered and jumped when the (hard-coded, no less) background image height was reached. So I fixed it:

  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  2.  
  3. <html>
  4.  
  5. <head>
  6. <!-- Original by Roy Sinclair. Update by r3dux, Nov 2010 --> 
  7. <title>JavaScript Background Scroller</title>
  8.  
  9. <script type="text/javascript">
  10. <!-- Hide script from browsers not playing nice w/ JavaScript
  11.  
  12.         // Function to scroll out background image
  13.        function scrollBackground(imageWidth, imageHeight) {
  14.  
  15.             // Set our background offset. First field is horizontal offset, 2nd is vertical
  16.             bgObject.style.backgroundPosition = horizOffset + " " + vertOffset;
  17.  
  18.             // Move image offset by given speeds
  19.             horizOffset += horizSpeed;
  20. 	    vertOffset  += vertSpeed;
  21.  
  22.             // Reset our offsets when we've gone over (under if moving left or up) the size of the background image
  23. 	    if (Math.abs(horizOffset) > imageWidth)
  24. 	    {   
  25.                 if (horizOffset > 0)
  26. 		{
  27. 			horizOffset -= imageWidth;
  28. 		}
  29. 		else
  30. 		{
  31. 			horizOffset += imageWidth;
  32. 		}
  33.             }
  34.  
  35. 	    if (Math.abs(vertOffset) > imageHeight)
  36. 	    { 
  37. 		if (horizOffset > 0)
  38. 		{
  39. 			vertOffset -= imageHeight;
  40. 		}
  41. 		else
  42. 		{
  43. 			vertOffset += imageHeight;
  44. 		}
  45.             }
  46.  
  47.        } // End of scrollBackground function
  48.  
  49. // End of JavaScript--> 
  50. </script>
  51.  
  52. </head>
  53.  
  54. <!-- Kick off the document body and use our background image -->
  55. <body background="./AU-Flag.gif">
  56.  
  57. <script type="text/javascript">
  58. <!-- Hide script from browsers not playing nice w/ JavaScript
  59.  
  60.     // Movement controlling variables:
  61.     // horizSpeed - positive values move the background to the right, negative to the left
  62.     // vertSpeed  - positive values move the background downwards, negative values move it upwards
  63.     // (Feel free to use fractional values, too i.e. 0.3 etc.)
  64.     // updateDelay - how many milliseconds to wait before updating the screen with the new background position
  65.     // (1000 ms in 1 second, lower values will move the background more often so it will appear to move faster, at the cost of increased CPU usage)
  66.     var horizSpeed = 1; 
  67.     var vertSpeed = 1.5;
  68.     var updateDelay = 50;
  69.  
  70.     // Grab our background image
  71.     var imgFile = new Image();
  72.     imgFile.src = "./AU-Flag.gif"
  73.  
  74.     // Get the height and width of the image
  75.     var imgHeight = imgFile.height;
  76.     var imgWidth  = imgFile.width;
  77.  
  78.     // Set our initial background offset
  79.     var horizOffset = 0;
  80.     var vertOffset = 0;
  81.  
  82.     // Get our background var as the document body
  83.     var bgObject = eval('document.body');
  84.  
  85.     // Kick off the scrolling. The second field is delay between updates in milliseconds.
  86.     var ScrollTimer = window.setInterval("scrollBackground(" + imgWidth + "," + imgHeight + ")", updateDelay);
  87.  
  88. // End of JavaScript--> 
  89. </script>
  90.  
  91. </body>
  92.  
  93. </html>

You can see it in action here. WoW! LoL! =P

Yeah… Gonna go with Flash CS4, methinks. But still, bit ‘o fun & all that…

P.S. If the background image doesn’t scroll, try re-loading the page… Not sure why but sometimes it just won’t go without having to do that… Very odd =/