glReadBuffer (aDrawBufferPrev);
   }
 
-  GLint anAlignBack = 1;
-  glGetIntegerv (GL_PACK_ALIGNMENT, &anAlignBack);
-  GLint anExtraBytes = (GLint )theImage.RowExtraBytes();
-  GLint anAligment   = Min (GLint(theImage.MaxRowAligmentBytes()), 8); // limit to 8 bytes for OpenGL
+  // setup alignment
+  const GLint anExtraBytes = (GLint )theImage.RowExtraBytes();
+  const GLint anAligment   = Min (GLint(theImage.MaxRowAligmentBytes()), 8); // limit to 8 bytes for OpenGL
   glPixelStorei (GL_PACK_ALIGNMENT, anAligment);
 
-  if (anExtraBytes >= anAligment)
+  const GLint aPixelsWidth = GLint(theImage.SizeRowBytes() / theImage.SizePixelBytes());
+  glPixelStorei (GL_PACK_ROW_LENGTH, (anExtraBytes >= anAligment) ? aPixelsWidth : 0);
+
+  if (theImage.IsTopDown())
   {
     // copy row by row
     for (Standard_Size aRow = 0; aRow < theImage.SizeY(); ++aRow)
     {
-      glReadPixels (0, GLint(aRow), GLsizei (theImage.SizeX()), 1, aFormat, aType, theImage.ChangeRow (aRow));
+      // Image_PixMap rows indexation always starts from the upper corner
+      // while order in memory depends on the flag and processed by ChangeRow() method
+      glReadPixels (0, GLint(theImage.SizeY() - aRow - 1), GLsizei (theImage.SizeX()), 1, aFormat, aType, theImage.ChangeRow (aRow));
     }
   }
   else
   {
-    // read pixels
     glReadPixels (0, 0, GLsizei (theImage.SizeX()), GLsizei (theImage.SizeY()), aFormat, aType, theImage.ChangeData());
-    theImage.SetTopDown (false); // image bottom-up in OpenGL
   }
 
-  glPixelStorei (GL_PACK_ALIGNMENT, anAlignBack);
+  glPixelStorei (GL_PACK_ALIGNMENT,  1);
+  glPixelStorei (GL_PACK_ROW_LENGTH, 0);
 
   if (theFBOPtr != NULL && theFBOPtr->IsValid())
   {
 
 IMPLEMENT_STANDARD_HANDLE (OpenGl_Texture, OpenGl_Resource)
 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Texture, OpenGl_Resource)
 
+//! Simple class to reset unpack alignment settings
+struct OpenGl_UnpackAlignmentSentry
+{
+
+  //! Reset unpack alignment settings to safe values
+  void Reset()
+  {
+    glPixelStorei (GL_UNPACK_ALIGNMENT,  1);
+    glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
+  }
+
+  ~OpenGl_UnpackAlignmentSentry()
+  {
+    Reset();
+  }
+
+};
+
 // =======================================================================
 // function : OpenGl_Texture
 // purpose  :
   GLint aTestWidth  = 0;
   GLint aTestHeight = 0;
 
-  glPixelStorei (GL_UNPACK_ALIGNMENT, 1); // ensure alignment will not screw up the party
+  // setup the alignment
+  OpenGl_UnpackAlignmentSentry anUnpackSentry;
+  const GLint anAligment = Min ((GLint )theImage.MaxRowAligmentBytes(), 8); // OpenGL supports alignment upto 8 bytes
+  glPixelStorei (GL_UNPACK_ALIGNMENT, anAligment);
+
+  // notice that GL_UNPACK_ROW_LENGTH is not available on OpenGL ES 2.0 without GL_EXT_unpack_subimage extension
+  const GLint anExtraBytes = GLint(theImage.RowExtraBytes());
+  const GLint aPixelsWidth = GLint(theImage.SizeRowBytes() / theImage.SizePixelBytes());
+  glPixelStorei (GL_UNPACK_ROW_LENGTH, (anExtraBytes >= anAligment) ? aPixelsWidth : 0);
+
   switch (theType)
   {
     case Graphic3d_TOT_1D:
       GLvoid* aDataPtr = (GLvoid* )theImage.Data();
       if (aWidth != aWidthOut)
       {
+        glPixelStorei (GL_PACK_ALIGNMENT,  1);
+        glPixelStorei (GL_PACK_ROW_LENGTH, 0);
         if (!aCopy.InitTrash (theImage.Format(), Standard_Size(aWidthOut), 1)
           || gluScaleImage (aPixelFormat,
                             aWidth,    1, aDataType, theImage.Data(),
         }
 
         aDataPtr = (GLvoid* )aCopy.Data();
+        anUnpackSentry.Reset();
       }
 
       // use proxy to check texture could be created or not
       if (aWidth != aWidthOut || aHeight != aHeightOut)
       {
         // scale texture
+        glPixelStorei (GL_PACK_ALIGNMENT,  1);
+        glPixelStorei (GL_PACK_ROW_LENGTH, 0);
         if (!aCopy.InitTrash (theImage.Format(), Standard_Size(aWidthOut), Standard_Size(aHeightOut))
           || gluScaleImage (aPixelFormat,
                             aWidth,    aHeight,    aDataType, theImage.Data(),
         }
 
         aDataPtr = (GLvoid* )aCopy.Data();
+        anUnpackSentry.Reset();
       }
 
       // use proxy to check texture could be created or not
 
--- /dev/null
+puts "============"
+puts "OCC23813"
+puts "============"
+puts ""
+#######################################################################
+# TKOpenGl, OpenGl_Texture ignores stride image property
+#######################################################################
+
+file delete -force ${imagedir}/texture_412.png
+file delete -force ${imagedir}/texture_409.png
+
+box b 1 2 3 
+vinit
+vsetdispmode 1
+vdisplay b
+vfit
+vdump ${imagedir}/texture_409.png rgb 409 409
+vdump ${imagedir}/texture_412.png rgb 412 412
+
+# texture loaded correctly
+vtexture b ${imagedir}/texture_412.png
+
+# texture is corrupted during uploading to OpenGL
+vtexture b ${imagedir}/texture_409.png
+
+set only_screen 1