Announcement

Collapse
No announcement yet.

Rotating a product image. gdImageCopyRotated()

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Rotating a product image. gdImageCopyRotated()

    I know the location of an image file "graphics/00000001/product_code_71x250.jpg" but I need to rotate it 90 deg.

    Does anyone have an example of how to use this function?

    gdImageCopyRotated( dst, src, dstX, dstY, srcX, srcY, srcWidth, srcHeight, angle )
    Ray Yates
    "If I have seen further, it is by standing on the shoulders of giants."
    --- Sir Isaac Newton

    #2
    Re: Rotating a product image. gdImageCopyRotated()

    Ok I downloaded the gd library and am looked through the source code and examples.

    I figured out I must (1.) load the jpeg file and (2.) create a blank destination jpeg in memory then (3.) use the command above to rotate the image, then (4.) I can save the new image.

    Step 1: load the image ( I'm so confused :O ) Where did the loaded image data go?

    Code:
    <MvASSIGN NAME="l.imgfile" VALUE="splitboard_193x250.jpg">
    <img src="{ l.imgfile }"><br>
    
    <MvASSIGN NAME="l.src" VALUE="{ gdImageCreateFromJpeg(l.imgfile, 'script') }">
    <MvEVAL EXPR="{ 'l.src = ' $ l.src $ ' <hr>' }">
    
    <MvEXIT>
    This outputs 1. If the file is not found it outputs -1. Shouldn't l.src contain the data?

    C Code Snipit
    Code:
    gdImagePtr loadImage(const char *name)
    {
        FILE *fp;
        gdImagePtr im;
    
        fp = fopen(name, "rb");
        if (!fp) {
            fprintf(stderr, "Can't open jpeg file\n");
            return NULL;
        }
    
        im = gdImageCreateFromJpeg(fp);
        fclose(fp);
        return im;
    }
    Ray Yates
    "If I have seen further, it is by standing on the shoulders of giants."
    --- Sir Isaac Newton

    Comment


      #3
      Re: Rotating a product image. gdImageCopyRotated()

      I see that the LSK now has a number of image functions but using it, l.src still outputs a 1
      Ray Yates
      "If I have seen further, it is by standing on the shoulders of giants."
      --- Sir Isaac Newton

      Comment


        #4
        Re: Rotating a product image. gdImageCopyRotated()

        For posterity, here is my solution.

        Code:
        <MvCOMMENT>
            rotate_image.mv By Ray Yates 8/15/2014
            Usage:
                gd_Rotate(l.input_image_file, l.output_image_file, l.angle)
        
            GD Library Documentation www.boutell.com/gd/manual2.0.33.html
        </MvCOMMENT>
        
        <MvASSIGN NAME="g.ImgInfile" VALUE="/mm5/graphics/00000001/splitboard_14_15_193x250.jpg">
        <MvASSIGN NAME="g.ImgOutfile" VALUE="/mm5/graphics/00000001/splitboard_14_15_193x250_r.jpg">
        
        <MvIF EXPR="{ gd_Rotate(g.ImgInfile, g.ImgOutfile, 90*3) LT 0 }">
            <MvEVAL EXPR="{ 'Error in: gd_Rotate()' $ ' <br>' }">
        <MvELSE>
            <img src="{ g.ImgInfile }"><br>
            <img src="{ g.ImgOutfile }"><br>
        </MvIF>
        
        <MvEXIT>
        
        <MvFUNCTION NAME="gd_Rotate" PARAMETERS="infile, outfile, angle" STANDARDOUTPUTLEVEL="">
            <MvASSIGN NAME="l.location" VALUE="script">
        
            <MvIF EXPR = "{ NOT [g.module_library_utilities].Image_Type( l.infile, l.location, l.type ) }">
                <MvFUNCTIONRETURN VALUE = 0>
            </MvIF>
        
            <MvCOMMENT> Allow merchant to handle file errors </MvCOMMENT>
            <MvASSIGN NAME="l.imageSrc" VALUE="{ [g.module_library_utilities].Image_gdCreateFromFile_Type( l.type, l.infile, l.location ) }">
        
            <MvIF EXPR="{ l.imageSrc LT 0 }">
                <MvFUNCTIONRETURN VALUE=0>
            </MvIF>
        
            <MvASSIGN NAME="l.source_width" VALUE="{ gdImageSX( l.imageSrc ) }">
            <MvASSIGN NAME="l.source_height" VALUE="{ gdImageSY( l.imageSrc ) }">
            <MvASSIGN NAME="l.output_width" VALUE="{ l.source_height }">
            <MvASSIGN NAME="l.output_height" VALUE="{ l.source_width }">
        
            <MvASSIGN NAME="l.imageDst" VALUE="{ gdImageCreateTrueColor( l.output_width, l.output_height ) }">
        
            <MvCOMMENT> Optional transparent black background
            <MvASSIGN NAME="l.black" VALUE="{ gdImageColorAllocate( l.imageDst, 0, 0, 0 ) }">
            <MvASSIGN NAME="l.void" VALUE="{ gdImageFilledRectangle( l.imageDst, 0, 0, l.output_width, l.output_height, l.black) }">
            <MvASSIGN NAME="l.void" VALUE="{ gdImageColorTransparent( l.imageDst, l.black) }">
            </MvCOMMENT>
        
            <MvASSIGN NAME="l.void" VALUE="{ gdImageCopyRotated(l.imageDst, l.imageSrc, floor(l.output_width/2), floor(l.output_height/2), 0,0, l.source_width, l.source_height, l.angle) }">
            <MvASSIGN NAME="l.void" VALUE="{ gdImageDestroy( l.imageSrc ) }">
        
            <MvCOMMENT> Force image quality to 100</MvCOMMENT>
            <MvIF EXPR="{ g.Domain:img_qual }">
                <MvASSIGN NAME="l.save_img_qual" VALUE="{ g.Domain:img_qual }">
            </MvIF>
            <MvASSIGN NAME="g.Domain:img_qual" VALUE="100">
        
            <MvCOMMENT> Allow merchant to handle file errors </MvCOMMENT>
            <MvASSIGN NAME="l.result" VALUE="{ [g.module_library_utilities].Image_gdSaveToFile_Type( l.imageDst, l.type, l.outfile, l.location ) }">
            <MvIF EXPR="{ l.save_img_qual }">
                <MvASSIGN NAME="g.Domain:img_qual" VALUE="{ l.save_img_qual }">
            </MvIF>
        
            <MvFUNCTIONRETURN VALUE="{ l.result }">
        </MvFUNCTION>
        Ray Yates
        "If I have seen further, it is by standing on the shoulders of giants."
        --- Sir Isaac Newton

        Comment


          #5
          Re: Rotating a product image. gdImageCopyRotated()

          Standing O for posterity...don't know if I'll ever use this, but the example is great...need more of these :)
          Bruce Golub
          Phosphor Media - "Your Success is our Business"

          Improve Your Customer Service | Get MORE Customers | Edit CSS/Javascript/HTML Easily | Make Your Site Faster | Get Indexed by Google | Free Modules | Follow Us on Facebook
          phosphormedia.com

          Comment


            #6
            Re: Rotating a product image. gdImageCopyRotated()

            Thanks Bruce!

            One thing the destination image should be removed from memory before exiting the function, (like closing your open files before exiting).

            Code:
                <MvASSIGN NAME="l.void" VALUE="{ gdImageDestroy( l.imageDst ) }">
                <MvFUNCTIONRETURN VALUE="{ l.result }">
            Earlier in the post I was confused when gdImageCreateFromJpeg(l.imgfile, 'script') returned a 1

            The 1 is a pointer to memory structures stored within the gd library itself. As you execute more of these commands new structures are created and the pointers increment.

            Initially I was calling this function in a loop so it was allocating more and more memory.

            Images in memory will persist so you could operate on it within another MivaScript function by returning the pointer and then call gdImageDestroy(pointer) later.
            Ray Yates
            "If I have seen further, it is by standing on the shoulders of giants."
            --- Sir Isaac Newton

            Comment


              #7
              Re: Rotating a product image. gdImageCopyRotated()

              Hi Ray,
              Thanks for a great post. I was stunned to think that the gd library could tie up the memory with an infinite number of images.

              But why should gd collect its garbage when that's the developer's job.

              I had always thought that the garbage would die with the MIVA function so its good to know that encapsulation does not provide closure and to use destroy as a best practice.

              I read that php had memory management problems with the gd library so after php4 the Zend engine collects the resources with no more references.

              This is probably a server management issue but I wonder how Miva handles the issue of garbage collection and orphaned db connections.
              http://www.alphabetsigns.com/

              Comment


                #8
                Re: Rotating a product image. gdImageCopyRotated()

                Originally posted by alphabet View Post
                Hi Ray,
                This is probably a server management issue but I wonder how Miva handles the issue of garbage collection and orphaned db connections.
                We clean up any remaining gd images, database connections and other memory when the script terminates.

                Comment


                  #9
                  Re: Rotating a product image. gdImageCopyRotated()

                  Thanks Burch, I feel better. :)
                  http://www.alphabetsigns.com/

                  Comment


                    #10
                    Re: Rotating a product image. gdImageCopyRotated()

                    Originally posted by alphabet View Post
                    Hi Ray,
                    Thanks for a great post. I was stunned to think that the gd library could tie up the memory with an infinite number of images.

                    But why should gd collect its garbage when that's the developer's job.
                    As Jon said, allocating image memory only happens while the script is running. The engine cleans up after exiting.

                    I was creating a custom category page and needed to rotate the images for some compare product pages. It only had 8 or so images but as long as the script was running the memory had not been de-allocated. If I have been, for example, batch processing ALL of the product images to provide a rotated view, it could quickly fill up available memory.

                    I have subsequently broken this function up into several components to start my own gd library.

                    gd_ImgOpen(), gd_ImgClose(), gd_ImgType(), gd_CanvasSizeMem(), gd_ImgRotateMem(), hex2rgb(hexColor)

                    The LSK contains Image_ResizeIntoBoundingBox()

                    For this project I used Toolbelts do command in a page template and called Image_ResizeCanvas_Rotate_Save(srcPath, dstImg). I then output the dstImg:path to the page.

                    On the category page an Ajax call returns the rotated image path and I swap out the images.

                    I won't post the library here, but this function might prove useful.

                    Code:
                    <MvFUNCTION NAME="hex2rgb" PARAMETERS="hexColor" STANDARDOUTPUTLEVEL="">
                        <MvCOMMENT>
                            hex2rgb('#E19C65') returns an rgb array containing 225,156,101
                        </MvCOMMENT>
                    
                        <MvASSIGN NAME="l.hexColor" VALUE="{ toupper(glosub(l.hexColor,'#','')) }">
                        <MvIF EXPR="{ len(l.hexColor) NE 6 }">
                            <MvFUNCTIONRETURN VALUE="">
                        </MvIF>
                        <MvASSIGN NAME="l.hex_chars" VALUE="0123456789ABCDEF">
                    
                        <MvFOR INDEX = "l.pos" COUNT = "{ 3 }">
                            <MvASSIGN NAME="l.n" VALUE="{ l.pos * 2 - 1 }">
                            <MvASSIGN NAME="l.int1" VALUE="{ (substring(l.hexColor,l.n,1) IN l.hex_chars) - 1 }">
                            <MvASSIGN NAME="l.int2" VALUE="{ (substring(l.hexColor,l.n+1,1) IN l.hex_chars) - 1 }">
                            <MvASSIGN NAME="l.rgb" INDEX="{ miva_array_max(l.rgb) + 1 }" VALUE="{ (l.int1 * 16) + l.int2 }">
                        </MvFOR>
                    
                        <MvFUNCTIONRETURN VALUE="{ l.rgb }">
                    </MvFUNCTION>
                    Last edited by RayYates; 08-21-14, 04:32 AM.
                    Ray Yates
                    "If I have seen further, it is by standing on the shoulders of giants."
                    --- Sir Isaac Newton

                    Comment

                    Working...
                    X